写代码啦
虚拟 DOM 和 DOM diff
回复数(0) 浏览数(87)
{{topic.upvote_count || 0}} 编辑 回复

虚拟 DOM 是什么

虚拟DOM是相对真实DOM的一个概念。他实际是把DOM对象抽象起来成一个javascript对象。虚拟DOM是和新一代框架组件概念想对应的。在框架内部可以对虚拟DOM进行diff来达到优化的效果。

虚拟 DOM 的优点和缺点

优点有:
1. 减少 DOM 操作
虚拟 DOM 可以将多次操作合并为一次操作,比如你添加 1000 个节点,却是一个接一个操作的(减少频率)。虚拟 DOM 借助 DOM diff 可以把多余的操作省掉,比如你添加 1000 个节点,其实只有 10 个是新增的(减少范围)
2. 跨平台
虚拟 DOM 不仅可以变成 DOM,还可以变成小程序、iOS 应用、安卓应用,因为虚拟 DOM 本质上只是一个 JS 对象

缺点有:

  1. 某些情况下,虚拟DOM的执行效率不如真实DOM操作
  2. 需要额外的创建函数,如 createElement 或 h,但可以通过 JSX 来简化成 XML 写法

DOM diff 是什么

要问DOM diff是什么,首先要明白即便是虚拟DOM也存在更新问题。也就是DOM树的比较。DOM diff就一种比较的算法。要完整的比较两个树,算法的时间复杂度是O(n^3),这意味着如果要展示1000个节点,就要依次执行上十亿次的比较。这显示是不能接受的。那么就需要根据一些DOM特性来设计更好的算法。以React为例,他主要遵循两个前提:

  1. 两个不同类型的元素会产生不同的树
  2. 对于同一层级的一组子节点,它们可以通过唯一 key 进行区分

大致的逻辑:

Tree diff

  1. 将新旧两棵树逐层对比,找出哪些节点需要更新
  2. 如果节点是组件就看 Component diff
  3. 如果节点是标签就看 Element diff
    ## Component diff
    1.如果节点是组件,就先看组件类型
  4. 类型不同直接替换(删除旧的)
  5. 类型相同则只更新属性
  6. 然后深入组件做 Tree diff(递归)
    ## Element diff
  7. 如果节点是原生标签,则看标签名
  8. 标签名不同直接替换,相同则只更新属性
  9. 然后进入标签后代做 Tree diff(递归)

DOM diff 的优点

保持完整的结构,有利于性能的提升

DOM diff 的问题(key)

同级节点对比存在 bug, 点开这个的链接

image.png image.png

当你删除中间的li元素,会发现实际删除的是最后一个元素,这是因为旧的数组有三个元素,新的数组有两个元素,算法不知道其中的区别,以为是最后一个元素没删除了.这时候就需要key了.

如果在遍历li的时候,加上了key,作为当前层次的唯一标识,那么算法就知道是删除中间的元素.

{{topic.upvote_count || 0}}

虚拟 DOM 是什么

虚拟DOM是相对真实DOM的一个概念。他实际是把DOM对象抽象起来成一个javascript对象。虚拟DOM是和新一代框架组件概念想对应的。在框架内部可以对虚拟DOM进行diff来达到优化的效果。

虚拟 DOM 的优点和缺点

优点有:
1. 减少 DOM 操作
虚拟 DOM 可以将多次操作合并为一次操作,比如你添加 1000 个节点,却是一个接一个操作的(减少频率)。虚拟 DOM 借助 DOM diff 可以把多余的操作省掉,比如你添加 1000 个节点,其实只有 10 个是新增的(减少范围)
2. 跨平台
虚拟 DOM 不仅可以变成 DOM,还可以变成小程序、iOS 应用、安卓应用,因为虚拟 DOM 本质上只是一个 JS 对象

缺点有:

  1. 某些情况下,虚拟DOM的执行效率不如真实DOM操作
  2. 需要额外的创建函数,如 createElement 或 h,但可以通过 JSX 来简化成 XML 写法

DOM diff 是什么

要问DOM diff是什么,首先要明白即便是虚拟DOM也存在更新问题。也就是DOM树的比较。DOM diff就一种比较的算法。要完整的比较两个树,算法的时间复杂度是O(n^3),这意味着如果要展示1000个节点,就要依次执行上十亿次的比较。这显示是不能接受的。那么就需要根据一些DOM特性来设计更好的算法。以React为例,他主要遵循两个前提:

  1. 两个不同类型的元素会产生不同的树
  2. 对于同一层级的一组子节点,它们可以通过唯一 key 进行区分

大致的逻辑:

Tree diff

  1. 将新旧两棵树逐层对比,找出哪些节点需要更新
  2. 如果节点是组件就看 Component diff
  3. 如果节点是标签就看 Element diff
    ## Component diff
    1.如果节点是组件,就先看组件类型
  4. 类型不同直接替换(删除旧的)
  5. 类型相同则只更新属性
  6. 然后深入组件做 Tree diff(递归)
    ## Element diff
  7. 如果节点是原生标签,则看标签名
  8. 标签名不同直接替换,相同则只更新属性
  9. 然后进入标签后代做 Tree diff(递归)

DOM diff 的优点

保持完整的结构,有利于性能的提升

DOM diff 的问题(key)

同级节点对比存在 bug, 点开这个的链接

image.png image.png

当你删除中间的li元素,会发现实际删除的是最后一个元素,这是因为旧的数组有三个元素,新的数组有两个元素,算法不知道其中的区别,以为是最后一个元素没删除了.这时候就需要key了.

如果在遍历li的时候,加上了key,作为当前层次的唯一标识,那么算法就知道是删除中间的元素.

87
回复 编辑