笔记
前段时间面试小米被问到vue的响应式原理。然后粗略的回答了发布者订阅者模式,Object.defineProperty(),感觉面试官不是很满意,我自己其实当时答的也没底
记录
js中Object.defineProperty()用来在一个对象上定义一个新的属性或者修改已存在的属性。
Object.defineProperty(obj,key,value)
obj修改的对象
key属性
value值
但是在vue里面,因为修改的值不知一个,所以第三个参数常被写成一个对象格式
通过里面调用一个get()方法和set()方法去完成相应的操作
Object.defineProperty(obj,key,{
set(newValue){
console.log('修改'+newValue)
//获取修改的属性值
}
get(){
console.log('操作的key是'+key)
//获取修改的值
}
})
如果你修改obj属性的值会出现以下输出
obj.name = 'aaa'
//=>修改aaa
obj.name
//=>操作的key是name
所以我们可以结合订阅者发布者模式在set里面做通知需要修改的属性进行修改在get里面获取到需要修改的属性
定义一个发布者
//ES6
class Dep{
constructor() {
this.sub = []
//存放订阅者
}
adddep(name){
this.sub.push(name)
}
//添加订阅者
notify(){
//分别给订阅者发布更新
this.sub.forEach(items=>{
tems.update()
})
}
}
定义一个订阅者
class Watcher{
constructor(name){
this.name = name
}
update(){
//更新操作
console.log(this.name + '更新')
}
}
const dep1 = new Dep()
const w1 = new Watcher('A1')
dep1.adddep(w1)
const w2 = new Watcher('A2')
dep1.adddep(w2)
const w3 = new Watcher('A3')
dep1.adddep(w3)
//如果改变就调用notify方法通知订阅者更新
dep1.notify()
基本过程就是这样。
每当new一个vue实例,它就会通过observe去监听页面上用的data属性是否改变,然后给他们每个都添加一个dep的对象,如果改变通知dep改变,然后通过complier去解析el模板,解析完会创建一个个的Watcher,然后Wather会给dep去添加一个个的订阅者,因为网页上用一个就添加一个。然后如果网页更新,dep会通过notify去通知相应的订阅者去调用他们的update方法去更新他们的值,这样就完成了vue的数据响应式实现
图解