Vue 虚拟DOM实现原理

Vue 的虚拟 DOM 参考了 snabbdom


1. 什么是虚拟DOM Virtual DOM

  • Virtual DOM(虚拟DOM),是由普通的JS对象来描述DOM对象
  • 真实DOM成员 – 属性太多
  • 使用 Virtual DOM 来描述真实DOM
{
    sel: "div",
    data: {},
    children: undefined,
    text: "Hello Virtual DOM",
    elm: undefined,
    key: undefined
}
 

2. 为什么要使用 Virtual DOM

  • MVVM 框架解决视图和状态同步问题
  • 模板引擎可以简化视图操作,没办法跟踪状态
  • 虚拟DOM跟踪状态变化

virtual-dom的动机描述 — 参考 github上的 virtual-dom

  • 虚拟DOM可以维护程序的状态,跟踪上一次的状态
  • 通过比较前后两次状态差异更新真实DOM

3. 虚拟DOM的作用

  • 维护视图和状态的关系
  • 复杂视图情况下提升渲染性能
  • 跨平台
    • 浏览器平台渲染DOM
    • 服务端渲染 SSR (Nuxt.js/Next.js)
    • 原生应用(Weex/React Native)
    • 小程序(mpvue/uni-app)等

虚拟DOM库

  • Snabbdom

    • Vue.js 2.x 内部使用的虚拟DOM就是改造的 Snabbdom
    • 大约 200SLOC(single line of code)
    • 通过模块可扩展
    • 源码使用 TypeScript 开发
    • 最快的 Virtual DOM 之一
  • virtual-dom

Diff 算法

快速记忆如下:
四种命中查找
1. 旧前新前
2. 旧后新后
3. 旧前新后
4. 旧后新前

3=> (此项发生了,那么旧前指向的节点,移动到旧后之后)
4=> (此项发生了,那么旧后指向的节点,移动的旧前之前)
 
  • 开始和结束节点 – 【旧前新前、旧后新后】

xx

  • 旧开始节点 / 新结束节点 – 【旧前新后】

gkSgje.png

  • 旧结束节点 / 新开始节点

gkSbjg.png

  • 非上述四种情况

gkPpCt.png

  • 循环结束
    • 当老节点的所有子节点先遍历完(oldStartIdx < oldEndIdx),循环结束
    • 新节点的所有子节点先遍历完(newStartIdx > newEndIdx),循环结束

gkFHg0.png

gkk1r8.png

四种命中查找

旧前与新前
旧后与新后
旧前与新后
旧后与新前

3=> (此项发生了,那么旧前指向的节点,移动到旧后之后)

else if (sameVnode(oldStartVnode, newEndVnode)) {
    patchVnode(oldStartVnode, newEndVnode)
    api.insertBefore(parentElm, oldStartVnode.elm, api.nextSibling(oldEndVnode.ele))
}
 

4=> (此项发生了,那么旧后指向的节点,移动的旧前之前)

else if (sameVnode(oldEndVnode, newStartVnode)) {
    patchVnode(oldEndVnode, newStartVnode)
    api.insertBefore(parentElm, oldEndVnode.elm, oldStartVnode.elm)
}
 

原创文章,作者:我心飞翔,如若转载,请注明出处:https://www.pipipi.net/14658.html

发表评论

登录后才能评论