前言
这是最近的碰到的那个 和响应式相关的问题 特定的操作之后响应式对象不“响应“了 引起的一系列的文章
主要记录的是 vue 的相关实现机制
呵呵 理解本文需要 vue 的使用基础, js 的使用基础
测试用例
测试用例如下, 一个简单的 按钮事件的触发
问题的调试
数据存放了两个地方, 第一个是 VueComponent 本身, 第二是 VueComponent._data 上面
VueComponent.counter 的 setter 是 proxySetter, proxySetter, VueComponent._data 的 setter 是 reactiveSetter
VueComponent.counter 的 setter 是 proxySetter, proxySetter 中会更新 VueComponent._data.counter 调用 VueComponent._data 的 setter, 进而调用了 reactiveSetter
Vue.prototype._render 里面渲染更新之后的节点
Vue.prototype._update 里面更新更新之后的节点
比如这里 vm.__patch__ 更新了当前组件下面的节点
父组件的 Watcher, 级联通知到 子组件, 是在 prepatch 中通知到 子组件 进行更新
renderChildren 中包含了需要重新渲染的 VNode
如何重新渲染?
这里的更新就是基于最基础的 js 的相关特性来进行更新的了
这里使用原生 js 大致操作一下该 div 的内容
子组件这边的三个层级的 vnode 分别对应于两个层级的 dom 元素, 加上内容元素
vnode 为 div.is-always-shadow 下面有一个 vnode 为 div.el-card__body
vnode 为 div.el-card__body 下面有一个 vnode 为 “你好 - 2” 的元素
patchVnode 的具体处理
首先是 prepatch 的回调
接着是 update 的回调
接着是 当前元素, 或者子元素的处理
如果更新前后子元素都存在, 递归更新子元素
如果更新前没有元素, 更新后有元素, 则表示新增 Vnode
如果更新前有元素, 更新后没有元素, 则表示移除 Vnode
如果更新前后当前元素的 text 不相同, 更新 textContent
接着是 postpatch 的回调
proxySetter - reactiveSetter - Dep - Watcher - VueComponent.update/render - VueComponent.patchVnode
一个组件对应于一个 VueComponent
一个 dom 元素对应于一个 VNode
一个 VueComponent 关联一个 Watcher, 关联一个 顶级VNode
关联 listeners, slots, props, route, router
完