Vue数据双向绑定原理
程序员文章站
2022-07-12 21:57:04
...
1、数据绑定渲染过程
- 创建实例
new Vue({...})
- 为实例中赋值el、data、methods等
this.$data = data
- 开启observer,监听data
Object.defineProperty()
- observer中为每一个observer中的监听属性生成对应订阅器
new Dep()
- 在get中等待订阅者加入,set中等待数据改变并通知订阅器更新视图
- 开启complier,创建文档碎片,将el整个劫持减少dom操作消耗
const $el = document.querySelectorAll(el)[0]
const fragment = document.createDocumentFragment()
fragement.appendChild($el)
- 遍历fragment所有节点属性找到指令属性以及特殊符号(如{{}})生成对应订阅者
[].slice.fragment.forEach(val => {
let attributes = val.attributes
[].slice.attributes.forEach(attr => {
// 获取所有节点属性,进行正则、判断等操作
....
// 生成对应订阅者传入参数
new Watcher(...)
})
})
- Watcher通知订阅器将自身加入(Watcher即订阅者,上面说到observer中get等待订阅者加入,可通过触发get属性)
// 通过访问触发订阅器对应get,将自身赋值给target供observer中get添加自身
target = this
let value = $vm.data[attr]
target = null
- Watcher须有一个update方法更新该订阅器对应的视图
Class Watcher{
constructor () {
...
}
update () {
...
}
}
- observer在get中收到则将订阅者添加进自身订阅器中
const dep = new Dep()
let value = obj[key]
Object.defineProperty(obj, key, {
get: () => {
target && dep.addSub(target)
},
set: (newVal) => {
if (newVal !== val) {
val = newVal
// 数据变动通知更新视图
dep.notify(newVal)
}
}
})
- 当数据变化时触发set,触发订阅器notify方法,调用该订阅器中每一个订阅者的update方法
class Dep{
constructor () {
this.sub = []
}
notify () {
this.sub.forEach(val => {
val.update()
})
}
addSub (target) {
this.sub.push(target)
}
}
- 触发watcher中的update替换数据,完成视图渲染
总结
初始化时监听data中的属性,为每个属性添加dep,运用闭包的原理等待watcher,之后开始编译模板,生成每个特殊指令对应的Watcher,通过触发对应data中的get将Watcher添加进去,当数据发生变化时通知该数据对应的每一个watcher,触发他们的update方法,完成数据绑定
上一篇: 【ACWing】479. 加分二叉树
下一篇: NMEA报文解析程序(c语言)-读报文