虚拟DOM和DOM diff

  • 虚拟DOM是什么

一个能代表 DOM 树的对象,通常含有标签名、标签上的属性、事件监听和子元素们,以及其他属性

  • 虚拟DOM的样子
React中
const vNode = {
  key: null,
  props: {
    children: [  // 子元素们
       { type: 'span', ... }, 
       { type: 'span', ... }
    ],
    className: "red" // 标签上的属性
    onClick: () => {} // 事件
  },
  ref: null,
  type: "div", // 标签名 or 组件名
  ...
}

复制代码
Vue中
const vNode = {
  tag: "div", // 标签名 or 组件名
  data: {
    class: "red", // 标签上的属性
    on: {
      click: () => {} // 事件
    }
  },
  children: [ // 子元素们
    { tag: "span", ... },
    { tag: "span", ... }
  ],
  ...
}

复制代码
  • 虚拟 DOM 有什么优点
  1. 减少 DOM 操作

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

  • 如何创建虚拟DOM
React.createElement
createElement('div',{className:'red',onClick:()=> {}},[
    createElement('span', {}, 'span1'),
    createElement('span', {}, 'span2')
  ]
)
复制代码
Vue(只能在 render 函数里得到 h)
h('div', {
  class: 'red',
  on: {
    click: () => { }
  },
}, [h('span',{},'span1'), h('span', {}, 'span2'])
复制代码
  • 简化创建虚拟DOM
React JSX
<div className="red" onClick="{()=> {}}">
    <span>span1</span>
    <span>span2</span>
</div>

复制代码
Vue Template
h('div', {
  class: 'red',
  on: {
    click: () => { }
  },
}, [h('span',{},'span1'), h('span', {}, 'span2'])

复制代码
  • 虚拟DOM的缺点

需要额外的创建函数,如 createElement 或 h,但可以通过 JSX 来简化成 XML 写法

-什么是DOM diff
虚拟 DOM 的对比算法
就是一个函数,我们称之为 patch
patches = patch(oldVNode, newVNode)

  • DOM diff 可能的大概逻辑

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

  • DOM diff 的缺点

同级节点对比存在 bug
参考阅读 Vue2.0 v-for 中 :key 到底有什么用
www.zhihu.com/question/61…

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享