Web前端之路

深入了解虚拟DOM

2019-06-19  本文已影响4人  尤小小

如果让我们自己开发一个视图框架

  1. state 数据
  2. render 模版
  3. 数据 + 模版 = 生成DOM结构 (Modle + View = DOM
  4. 当数据更新了,生成新的DOM结构
  5. 然后新DOM结构 替换老的DOM结构 (特别消耗性能)

将处理升级:

  1. state 数据
  2. render 模版
  3. 数据 + 模版 = 生成DOM结构 (Modle + View = DOM
  4. 当数据更新,生成新的DOM结构
  5. 比较新旧DOM结构差异 (input数据更新了)(DOM结构的比较diff 也很消耗性能)
  6. 然后将差异部分 替换成新的DOM结构

上面的方法虽然改进了,不直接替换DOM少消耗性能了,但是新旧DOM结构的比较也很消耗性能。

再次升级为虚拟DOM的处理:

  1. state 数据
  2. render 模版
  3. 数据 + 模版 = 生成DOM结构 (Modle + View = DOM
  4. 同时 生成 虚拟DOM 结构 (虽然生成虚拟DOM结构也消耗性能,但是用js生成一个js对象跟生成DOM结构相比,还是节省性能的)
  5. 当数据更新了,生产新的虚拟DOM结构 (也很快)
  6. 然后新旧虚拟DOM结构进行差异比较 (两个js对象或者数据比较 性能比 两个DOM结构比较高的多)
  7. 然后将差异部分进行替换

其实虚拟DOM就是 一个大的js对象或者数组。用js生成一个js对或者,进行两个对象的比较。要比生成一个DOM对象,进行两个DOM结构的比较性能要好的多 。

实际上react的实现:(3,4步是颠倒的)

  1. state 数据
  2. render 模版
  3. 数据 + 模版 = 生成 虚拟DOM 结构
  4. 虚拟DOM对象 生成真实的DOM (Modle + View = DOM
  5. 当state数据更新了
  6. 数据 + 模版 = 生成新的虚拟DOM结构 (极大地提升了性能)
  7. 然后新旧虚拟DOM结构进行差异比较 (两个js对象或者数据比较 性能比 两个DOM结构比较高的多)
  8. 然后将差异部分进行替换 操作DOM
render () {
    // JSX 语法 -> creactElement -> 虚拟DOM(js对象) -> 真实的DOM 
    return <div><span>item</span></div>
    return React.creactElement('div', {}, React.creactElement('span', {}, 'item'))
}

虚拟DOM的优点:

  1. 性能提升了
  2. 它使的跨端应用得以实现 React Native (js对象在网页、原生应用也可以识别)

虚拟DOM中的diff算法
第7步 两个虚拟DOM的比对就叫做 diffrence 找步同

思考:什么情况下会进行虚拟DOM的比对,🤔

  1. 数据更新了(state, props)
  2. 副组件的render执行了,子组件的render也执行

setState是异步的

为什么是异步的呢,是为了提升react底层的性能
比如说我们进行了三次setState的调用,这三次调用的间隔特别小,react会进行三次数据的更新 ,执行三次render吗? 实际上react只执行了一次render

diff算法 - 同层比对

两个虚拟DOM在进行比对的时候,它会进行同层比对,假设第一层 一致 再比对第二层,如果第一层就更新了,下面就不会在比了,整个进行新虚拟DOM转化为真实DOM,
可能会造成DOM的性能消耗。

diff算法 - key比对 (为什么模版遍历需要加key值)

without keys
有这样一个数组['item', 'item', 'item', 'item'],生成的DOM, 再没有key的时候两个虚拟DOM进行比较,可能要进行两成循环遍历,比较麻烦,也比较消耗性能。

with keys
如果每个元素上有key值,在进行虚拟DOM比较的时候,会和key值像关联,快速比对,就很容易知道 添加了什么,删除了什么。

在循环遍历的时候最好key值不要是index,能不用index做key, 就不要用index做key值。因为index的key值是不稳定的。
0 - a
1 - b
2 - c

现在把a删掉,此时
0 - b,
1 - c
两个虚拟DOM在进行比对,这样的话,用index就失去了意义了。

上一篇下一篇

猜你喜欢

热点阅读