第142篇:原生js实现响应式原理
好家伙,狠狠地补一下代码量
本篇我们来尝试使用原生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)
})functiondefineReactive(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();
}
});
}//依赖容器
functionDep() {
this.deps=[];
this.addDep= function(dep) {
this.deps.push(dep);
};
this.notify= function() {
this.deps.forEach(dep=>{
dep.update();
});
};
}
Dep.target= null;//Watcher
functionWatcher(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.补充
一张响应式原理图