2021-06-06记录:
vue响应式原理的基本流程: 初始化Vue实例时,Observer遍历data里所有属性,使用Object.defineProperty()方法把这些属性都转为getter/setter。并且创建dep管理器(一个属性一个Dep,用来管理该属性下的所有Watcher,如果同一个属性在DOM节点中多次使用会创建多个Watcher)
在解析指令时,创建Watcher,将更新函数放到Watcher的回调上。
初始化视图时,会读取属性值,触发get,将创建的Watcher添加到dep中。
当修改数据时,触发set,调用dep的notify,通知该dep内部所有Watcher的执行回调,重新render当前组件,生成新的虚拟DOM树。
Vue框架会遍历并对比新虚拟DOM树和旧虚拟DOM树种每个节点的差别,并记录下来,最后,加载操作,将所有记录的不同点,局部修改到真DOM树上。
Object.defineProperty()方法大家都知道,用来监测一个对象的值,通过getter和setter属性进行劫持属性的操作和更新
const data = {
name: '',
}
// 拷贝一下data对象 防止死循环
let newData = { ...data }
Object.defineProperty(data, 'name', {
get: () => {
console.log('读取')
return newData.name
},
set: (newval) => {
console.log('设置')
newData.name = newval
response()
},
})
setTimeout(() => {
data.name = 'hello world'
}, 1000)
//输入时为data重新赋值 通知监听的方法为newData更改数据来达到页面新数据的动态呈现
iptName.oninput = function () {
data.name = this.value
}
const response = () => {
hName.innerText = data.name
iptName.value = data.name
}
//简单实现一个Object.defineProperty()
创建Observer 递归监控劫持数据
现在开始考虑我们上面的data有多个属性,我们就需要一个方法或者类去遍历这个对象
//先为Object.defineProperty()封装一个公共的方法 并简化方法里面的操作
function defineReactive(data, key, value = data[key]) {
observe(value)//监听子属性
Object.defineProperty(data, key, {
get() {
return value
},
set(newValue) {
value = newValue
}
})
}
创建Observe函数去递归实现数据劫持
const observer =(data) => {
Object.keys(data).forEach((k) => defineReactive(data, k))
}
const data = {a:1,b:{c:1}}
observer(data)