- 流程:初始化数据 》 模板编译成 ast 语法树 》 变成 render() 》 生成虚拟 dom 》 变成真实 dom 》挂载到 el
- 模板编译 先找 render > template > el 里面的元素
- 通过 object.defineProperty 遍历,递归 实现数据劫持
- 数组通过重写数组原型方法实现数据劫持
- 与 vue.mixin() 注入的全局属性合并 options:{data:[] , created:[]}
- 通过 callHook 在不同时机触发
- dep 收集依赖 与 data 的属性一一对应
- dep 与 watcher 是多对多
- 当数据数据发生变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据改变。
- 如果同一个 watcher 被多次触发,只会被推入到队列中一次。
- 然后,在下一个的事件循环“tick”中,Vue 执行队列里的所有回调。
- 初始化遍历传入的watch对象,调用createWatcher创建Watcher
- watcher对象记录初始值,把自己添加到监听属性的dep上
- 当数据发生变化,依次触发watcher,用watcher上记录的旧值和新值调用watch对象传入的handler
- 用旧的虚拟dom和新的虚拟dom进行比对。
- 对比流程:前前——后后——交叉——暴力
- 添加多余的新vdom节点,删除多余的旧vdom节点
- 通过 object.defineProperty 把computed的属性代理到vue实例
- 给每一个 computed 属性创建 watcher 通过lazy属性实现懒加载 通过dirty属性实现缓存
- 用栈的方式让 computed 的 watcher 和页面更新的 watcher 都与 data 属性里面的dep绑定