小宋爱睡觉 小宋爱睡觉
首页
  • HTML
  • CSS
  • JavaScript
  • Vue
  • React
  • 计算机网络
  • 浏览器原理
  • 性能优化
  • 设计模式
手写系列
  • 字符串
  • 数组
  • 链表
  • 树
  • 动态规划
  • 排序算法
  • GitHub (opens new window)
  • JueJin (opens new window)
首页
  • HTML
  • CSS
  • JavaScript
  • Vue
  • React
  • 计算机网络
  • 浏览器原理
  • 性能优化
  • 设计模式
手写系列
  • 字符串
  • 数组
  • 链表
  • 树
  • 动态规划
  • 排序算法
  • GitHub (opens new window)
  • JueJin (opens new window)
  • Vue基础
  • Vue生命周期
  • 组件通信
  • Vue-Router
  • VueX
  • Vue3
  • VirtualDOM
    • 对虚拟DOM的理解
    • 虚拟dom的解析过程
    • 为什么要使用虚拟dom
    • vue 为什么采用 vdom
    • 虚拟DOM会比真实DOM性能好吗
    • diff算法的原理
    • Vue中key的作用
  • Vue
Crucials
2021-11-28

VirtualDOM

# Virtual DOM

# 对虚拟DOM的理解重要

从本质来说,虚拟dom就是一个js对象,通过对象的形式来表示dom结构,将页面的装填抽象成js对象,配合不同渲染工具可以更容易的跨平台,通过事物处理机制,将多次修改dom一次性更新到页面中,防止页面渲染多次,减少修改dom的重绘和重排,提高性能

设计虚拟dom就是为了更好的跨平台,比如nodejs就没有dom,想要达成ssr,就得借助虚拟dom,在代码渲染到页面之前,vue会将代码转化为虚拟dom,以对象的形式描述真实dom,每次变化之前,虚拟dom会缓存一份,和变化后的进行diff比较,重新渲染改变了的dom节点

# 虚拟dom的解析过程

  • 对要插入的文档的dom树进行分析,使用js对象表示出来(包含tagName,props,children等),然后保存起来,最后将dom片段插入文档

  • 当页面状态发生改变,需要对dom结构进行调整,根据变更的状态,重新构建一颗对象树,将新旧树进行对比,记录差异

  • 最后将有差异的地方应用到真实dom树上,就更新视图了

# 为什么要使用虚拟dom

  • 手动操作 DOM 比较麻烦,还需要考虑浏览器兼容性问题,虽然有 jQuery 等库简化 DOM 操作,但是随着项目的复杂 DOM 操作复杂提升
  • 为了简化 DOM 的复杂操作于是出现了各种 MVVM 框架,MVVM 框架解决了视图和状态的同步问题
  • 为了简化视图的操作我们可以使用模板引擎,但是模板引擎没有解决跟踪状态变化的问题,于是Virtual DOM 出现了
  • 保证性能的下限,提供过的去的性能,页面的渲染流程包括:解析HTML -> 生成dom -> 生成cssdom -> layout -> paint -> compile
    • 重排重绘性能消耗

      • 真实DOM:生成html字符串 -> 重建所有DOM元素
      • 虚拟DOM:生成vNode -> DOMdiff -> 必要的DOM更新

# vue 为什么采用 vdom 重要

引入 Virtual DOM 在性能方面的考量仅仅是一方面。

  • 性能受场景的影响是非常大的,不同的场景可能造成不同实现方案之间成倍的性能差距,所以依赖细粒度绑定及 Virtual DOM 哪个的性能更好还真不是一个容易下定论的问题。
  • Vue 之所以引入了 Virtual DOM,更重要的原因是为了解耦 HTML依赖,这带来两个非常重要的好处是:
  • 不再依赖 HTML 解析器进行模版解析,可以进行更多的 AOT 工作提高运行时效率:通过模版 AOT 编译,Vue 的运行时体积可以进一步压缩,运行时效率可以进一步提升;
  • 可以渲染到 DOM 以外的平台,实现 SSR、同构渲染这些高级特性,Weex等框架应用的就是这一特性。

综上,Virtual DOM 在性能上的收益并不是最主要的,更重要的是它使得 Vue 具备了现代框架应有的高级特性。

AOT是什么

AOT是Ahead-of-time compiler

模板编译的目的仅仅是将template转化为render function,这个过程,正好可以在项目构建的过程中完成,这样可以让实际组件在 runtime 时直接跳过模板渲染,进而提升性能,这个在项目构建的编译template的过程,就是预编译

  • 可以有更快的渲染速度:模版引擎的代码会预先被编译,优先给用户呈现
  • 更早检查出template错误并报告给程序员
  • 需下载的资源变少:预编译的影响只会在组件实例化的时候进行编译,生存render函数后不会进行二次编译,可以让实际组件在runtime时候跳过模版渲染

# 虚拟DOM会比真实DOM性能好吗

在首次渲染大量dom的时候由于多了一层虚拟dom的计算,会比innerHTML慢一些

但是他保证了性能的下限,在真实dom操作的时候进行针对性的优化(diff比较),还是更快的

# diff算法的原理重要

在新老节点的dom对比时:

  • 首先对比节点本身,判断是不是同一个节点

    • 如果不是就删除该节点重新创建节点来替换
    • 如果是的话,进行patchVnode,判断如何对该节点的子节点进行处理,首先判断一方有子节点一方没有的情况
    • 如果新的children没有子节点,就把旧的子节点去掉
    • 如果都有子节点,进行updateChildren,判断如何对这些新老子节点进行操作
  • 匹配时找到相同子节点,递归比较子节点

在diff中,只对同层的子节点进行比较,放弃跨级的比较,时间复杂度从O(n^3) -> O(n),也就是说当新旧children都为多个子节点才要核心的diff算法进行同层级比较

# Vue中key的作用

  • 在v-if中使用key,由于Vue会高效渲染元素,通常会复原已有元素而不是从头渲染,如果有相同类型的元素,那么元素就会复用,如果是相同的input元素也会复用,这样可能会出现input输入一开始就有值的情况,我们通过key来表示独立的元素

  • v-for使用key v-for更新已渲染过的元素列表,默认使用就地复用的策略,如果数据项顺序发生改变,vue不会移动dom来匹配顺序,而是简单复用,提供key来跟踪元素的身份高效更新虚拟DOM

我们不使用index作为key是因为,无论数组怎么颠倒顺序,index都是0,1,2,3,4这样排列,导致Vue会复用错误的旧节点

上次更新: 2022/02/19, 22:25:17
Vue3

← Vue3

Copyright © 2021-2025 粤ICP备2021165371号
  • 跟随系统
  • 浅色模式
  • 深色模式