vue双向绑定
1.什么是双向绑定?view更新视图,试图更新view. 4个步骤实现双向绑定, 实现一个监听者,对象属性发生变化则通知订阅者。 实现一个订阅者 实现一个订阅者watcher,收到属性变化并执行对应方法,从而更新视图。
监听器Observer实现
实现一个监听者,属性发生变化通知并执行相应的方法。 Object.defineProperty()劫持对象的getter,setter方法. 例子:
Object.defineProperty(obj, prop, descriptor)
var person = { name: "wang" }
Object.defineProperty(person, 'name', {
get() {
console.log('name被读取了')
return 'zhao'
},
set(newVal) {
console.log('name属性被修改了...');
val = newVal;
}
})
我们通过 object.defineProperty() 方法给 person 的 name 属性定义了 get() 和set()进行拦截,每当该属性进行读或写操作的时候就会触发get()和set()
如果要监听对象的每一个属性的话,一个一个设太麻烦。需要进行封装。 封装就是封装对象key,然后循环对象每个属性进行调用那个封装方法。
vue3版本双向绑定
let data={value:0}
const vm=new Proxy(data,{
set:function(target,key,newValue){
console.log('被赋值为'+newValue)
return true
},
get:function(target,key){
console.log('被读取咯')
return target[key]
}
})
vue3proxy代理的优点是不需要进行递归对对象属性进行监听。
订阅器实现
订阅器的例子:ajax的回调函数 success,error,只要在回调函数订阅即可,不需要监听其他函数。
生活小栗子:老师布置作业,所有学生了解作业,不需要老师通知每个学生作业的内容。
Deps中每个notify方法,都会自行更新每个sub。sub就是订阅者。addSub:添加订阅者。notify:订阅者方法。
function Dep() {
this.deps = []
}
Dep.prototype - {
addSub: function () {
this.deps.push(sub)
},
notify: function () {
this.deps.forEach((dep) => {
dep.update()
})
}
}
Dep.target=null //释放资源
四订阅器Watcher实现
function watcher(vm,exp,cb)
{
this.vm=vm;
this.exp=exp;
this.cb=cb;
this.value=this.get();
}
watcher.prototype={
update:function(){
this.run()
},
run:function(){
var value=this.vm.data[this.exp]
var oldValue=this.value;
if(value!==oldValue){
this.value=value;
this.cb.call(this.vm,value,oldValue)
}
},
get:function(){
Dep.target=this// 全局变量,订阅者
var value=this.vm.data[this.exp];
Dep.target=null //全局变量,订阅者 释放
return value
}
}