Open DeanTG opened 1 year ago
Virtual DOM 本质上是 JavaScript 对象,用 JS 来描述一个真实的 DOM 节点。
Virtual DOM 可以看做一棵模拟 DOM 树的 JavaScript 树,其主要是通过 VNode 实现一个无状态的组件,当组件状态发生更新时,然后触发 Virtual DOM 数据的变化,然后通过 Virtual DOM 和真实 DOM 的比对,再对真实 DOM 更新。可以简单认为 Virtual DOM 是真实 DOM 的缓存。
Vue 中 VNode 的类型:
diff 算法是一种通过同层的树节点进行比较的高效算法。diff 整体策略为:深度优先,同层比较
其有两个特点:
虚拟DOM最核心的部分是patch,它可以将vnode渲染成真实的DOM。
patch也可以叫作patching算法,通过它渲染真实DOM时,并不是暴力覆盖原有DOM,而是比对新旧两个vnode之间有哪些不同,然后根据对比结果找出需要更新的节点进行更新。
patch的过程:
原理分析 当数据发生改变时,set方法会调用Dep.notify通知所有订阅者Watcher,订阅者就会调用patch给真实的DOM打补丁,更新相应的视图 patch函数前两个参数位为oldVnode 和 Vnode ,分别代表新的节点和之前的旧节点,主要做了四个判断:
没有新节点,直接触发旧节点的destory钩子 没有旧节点,说明是页面刚开始初始化的时候,此时,根本不需要比较了,直接全是新建,所以只调用 createElm 旧节点和新节点自身一样,通过 sameVnode 判断节点是否一样,一样时,直接调用 patchVnode去处理这两个节点 旧节点和新节点自身不一样,当两个节点不一样的时候,直接创建新节点,删除旧节点
当数据发生改变时,订阅者watcher就会调用patch给真实的DOM打补丁 通过isSameVnode进行判断,相同则调用patchVnode方法 patchVnode做了以下操作: 找到对应的真实dom,称为el 如果都有都有文本节点且不相等,将el文本节点设置为Vnode的文本节点 如果oldVnode有子节点而VNode没有,则删除el子节点 如果oldVnode没有子节点而VNode有,则将VNode的子节点真实化后添加到el 如果两者都有子节点,则执行updateChildren函数比较子节点 updateChildren主要做了以下操作: 设置新旧VNode的头尾指针 新旧头尾指针进行比较,循环向中间靠拢,根据情况调用patchVnode进行patch重复流程、调用createElem创建一个新节点,从哈希表寻找 key一致的VNode 节点再分情况操作
link