好傢伙,狠狠地補一下程式碼量
本篇我們來嘗試使用原生js實現vue的響應式
使用原生js,即代表沒有v-bind,v-on,也沒有v-model,所有語法糖我們都用原生實現
1.給輸入框綁個變數
<body>
<input id="input_1"></input>
</body>
<script>
let datavalue = "66666"
const input_1 = document.getElementById("input_1")
input_1.value = datavalue
input_1.addEventListener('input', function(e) {
datavalue = e.target.value
console.log(datavalue)
})
</script>
誒,似乎這樣就完成了
但我們要讓他更像vue
2.加上Dep,Watcher
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input id="input_1"></input>
</body>
<script>
// 模擬 Vue 例項
let data = {
message: 'Hello'
};
const input_1 = document.getElementById("input_1")
input_1.value = data.message
input_1.addEventListener('input', function (e) {
e.target.value = data.message
console.log(datavalue)
})
function defineReactive(obj, key, value) {
let dep = new Dep(); // 依賴容器
Object.defineProperty(obj, key, {
get: function () {
if (Dep.target) {
dep.addDep(Dep.target);
}
return value;
},
set: function (newValue) {
value = newValue;
dep.notify();
}
});
}
// 依賴容器
function Dep() {
this.deps = [];
this.addDep = function (dep) {
this.deps.push(dep);
};
this.notify = function () {
this.deps.forEach(dep => {
dep.update();
});
};
}
Dep.target = null;
// Watcher
function Watcher(updateFunc) {
this.update = updateFunc;
}
// 初始化響應式資料
defineReactive(data, 'message', data.message);
// 模擬 Watcher
let watcher = new Watcher(function () {
console.log('Message updated:', data.message);
input_1.value = data.message
});
// 模擬檢視更新
Dep.target = watcher;
data.message; // 觸發依賴收集
setTimeout(() => {
data.message = '6666'; //觸發更新
}, 1000)
</script>
</html>
3.效果圖
4.程式碼解釋
-
defineReactive
函式用來定義一個響應式屬性,其中透過Object.defineProperty
給屬性新增 getter 和 setter 方法。在 getter 方法中,會判斷Dep.target
是否存在,如果存在則將當前 Watcher 物件新增到依賴容器 Dep 中;在 setter 方法中,更新屬性的值,並透過依賴容器 Dep 的notify
方法通知所有依賴的 Watcher 進行更新。 -
Dep
函式是一個簡單的依賴容器,其中包含了一個 deps 陣列用來儲存依賴(Watcher),addDep
方法用來新增依賴,notify
方法用來通知所有依賴進行更新。 -
Watcher
函式用來建立 Watcher 物件,其中包含一個update
方法,用來在屬性發生變化時執行相應的更新操作。 -
在初始化響應式資料時,呼叫
defineReactive
函式定義了一個名為message
的響應式屬性。 -
建立了一個 Watcher 物件
watcher
,並在其建構函式中定義了一個回撥函式,用來在屬性變化時輸出訊息並更新檢視。 -
將
watcher
賦值給Dep.target
,然後訪問data.message
,觸發依賴收集,將watcher
新增到依賴容器 Dep 中。
5.補充
一張響應式原理圖