set : 派发更新
Dep.notify()
watcher.update()
queenWatcher()
nextTick
flushScheduleQueue
watcher.run()
updateComponent()
大家可以先看下面的数据相应的代码实现后,理解后就比较容易看懂上面的简单脉络了。
- let data = {a: 1}
- // 数据响应性
- observe(data)
-
- // 初始化观察者
- new Watcher(data, 'name', updateComponent)
- data.a = 2
-
- // 简单表示用于数据更新后的操作
- function updateComponent() {
- vm._update() // patchs
- }
-
- // 监视对象
- function observe(obj) {
- // 遍历对象,使用 get/set 重新定义对象的每个属性值
- Object.keys(obj).map(key => {
- defineReactive(obj, key, obj[key])
- })
- }
-
- function defineReactive(obj, k, v) {
- // 递归子属性
- if (type(v) == 'object') observe(v)
-
- // 新建依赖收集器
- let dep = new Dep()
- // 定义get/set
- Object.defineProperty(obj, k, {
- enumerable: true,
- configurable: true,
- get: function reactiveGetter() {
- // 当有获取该属性时,证明依赖于该对象,因此被添加进收集器中
- if (Dep.target) {
- dep.addSub(Dep.target)
- }
- return v
- },
- // 重新设置值时,触发收集器的通知机制
- set: function reactiveSetter(nV) {
- v = nV
- dep.nofify()
- },
- })
- }
-
- // 依赖收集器
- class Dep {
- constructor() {
- this.subs = []
- }
- addSub(sub) {
- this.subs.push(sub)
- }
- notify() {
- this.subs.map(sub => {
- sub.update()
- })
- }
- }
-
- Dep.target = null
-
- // 观察者
- class Watcher {
- constructor(obj, key, cb) {
- Dep.target = this
- this.cb = cb
- this.obj = obj
- this.key = key
- this.value = obj[key]
- Dep.target = null
- }
- addDep(Dep) {
- Dep.addSub(this)
- }
- update() {
- this.value = this.obj[this.key]
- this.cb(this.value)
- }
- before() {
- callHook('beforeUpdate')
- }
- }
4. virtual dom 原理实现
|