看见一些老铁对于 何时更新 何时收集、何时render在提问区有些问题,因为老师这门课讲原理,不可能对各个方面都涉及,可能没有看过源码的人会懵一些, 因为源码包含全部的细节,对大家比较迷惑的部分从头写一下,也当作自己的一次回顾:如有不对的地方,欢迎指出
1. new Vue
代码中 const vm = new Vue(),实际触发了_init函数,定义如下(只保留关键步骤):
Vue.prototype._init = function () {
initLifecycle(vm)
//...各种init:Events、Hook(beforeCreate、created)
initState(vm); //★ 重点
...
vm.$mount(vm.$options.el) //★ 重点
}
其中initState 就是对 props、data等进行双向数据绑定,绑定get set 函数
2.mount (template->render)
mount就是挂载, 在init各种 之后,进行$mount
第一步:先将template->render 编译
第二步: 创建渲染Watcher
updateComponent = () => {
vm._update(vm._render(), hydrating)
},
new Watcher(vm, updateComponent,...) //负责整个dom渲染的watcher 重点
在这个watcher 内 会读取dom中用到的数据,也就触发了上面双向绑定的get,get内部进行依赖收集:
get: function reactiveGetter() {
//...
dep.depend(watcher) //watcher Dep.target 当前watcher
return value
},
set: function reactiveSetter(newVal) {
//...
dep.notify()
}
首先 watcher 和dep不了解各位老铁看资料吧,
通俗的讲: watcher1 用到了message属性,那么在触发message get的时候dep将这个watcher1 保存, 然后watcher2 也用到了message 那么就加入watcher2,此时 dep = [watcher1、watcher2],然后在message改变触发set的时候 ,遍历执行每一个watcher.update()…
3.render
上一步 初次渲染 new watcher 有一个回调函数,其中调用_render(就是template->render), 进行render 然后就按照老师说的 生成vnode、patch(elm,vnode)
上面是首次渲染的过程,更新过程同理: 触发set ->watcher.update->触发回调render->patch
总结如下:
//初次渲染
1.initState ->进行双向绑定
2.$mount->将template编译成render函数
3.执行渲染 触发属性get函数,将渲染watcher 收集到dep中
4.调用render 函数 生成vnode
5.patch(elm,vnode)
//更新
1.修改数据 触发属性set
2.然后dep.notify() ->watch.update 派发更新
3.触发render watcher 的render回调
4.生成新的vnode
5.patch(oldVnode,newVnode)