虚拟DOM和DOM diff

2021-04-05  本文已影响0人  Marshall3572

虚拟DOM是什么?

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

虚拟DOM的优点:

DOM每发生一次改变,浏览器都会进行一次完整的渲染(重排与重绘),有了虚拟DOM之后,DOM发生改变时先修改对应虚拟DOM,虚拟DOM的改变并不会直接渲染,而是等所有改变完成之后进行渲染,避免不必要的操作从而提高性能。

  1. 减少不必要的DOM操作(下边这两个例子要背下来)。
  1. 跨平台渲染:
    由于虚拟dom是个对象,所以可以跨平台并支持服务端渲染。

虚拟DOM长什么样子?

// Vue
const vDode = {
    tag: "div", //标签名 or 组件名
    data: {
        class: "red", // 标签上的属性
        on: {
            click: () => {} // 事件
        }
    },
    children: [
        {tag: "span", ...},
        {tag: "span", ...}
    ],
    ...
}

如何创建一个虚拟DOM

// ReactcreateElement
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')])

改进(用JSX简化创建虚拟DOM)

// React 通过babel 转为 createElement 形式
<div className="red" onClick = {fn}>
    <span>span1</span>
    <span>span2</span>
</div>
// Vue 通过vue-loader转换为 h 形式
<div class="red" @click="fn">
    <span>span1<span>
    <span>span2<span>
</div>

虚拟DOM的缺点

当首次渲染大量DOM或者全部DOM,因为多了一层虚拟DOM的计算,反而比直接渲染慢
需要额外的创建函数,比如createElement(React)或h(Vue),但可以通过JSX来简化成XML写法。

DOM diff

什么是DOM diff?
DOM diff就是比较两个虚拟DOM之间有什么差异的算法
DOM diff就是一个函数,我们称之为patch
patches = patch(oldVNode, newVNode)
patches 就是我们要运行的DOM操作。
DOM diff的大概逻辑
将新旧两棵树逐层对比,找出哪些节点需要更新。
如果节点是组件就看Component diff,如果检点是标签就看Element diff
Component diff
如果节点是组件,就看组件类型,类型不同直接替换(删除旧的),类型相同就只更新属性,然后深入组件做Tree diff(递归)
Element diff
如果节点是原生标签,则看标签名,标签名不同直接替换,相同则只更新属性。然后进入标签后代做Tree diff(递归)。
DOM diff的优点
对比新旧节点,查找出差异并只修改差异部分,极大提高性能。
DOM diff的问题(key)
当虚拟DOM没有唯一标识符(key)时,默认以索引作为标识,那么两个相同的节点由于索引不同依然会进行修改删除等操作。

上一篇 下一篇

猜你喜欢

热点阅读