深入了解虚拟DOM
2019-06-19 本文已影响4人
尤小小
如果让我们自己开发一个视图框架
-
state
数据 -
render
模版 - 数据 + 模版 = 生成DOM结构 (Modle + View = DOM)
- 当数据更新了,生成新的DOM结构
- 然后新DOM结构 替换老的DOM结构 (特别消耗性能)
将处理升级:
-
state
数据 -
render
模版 - 数据 + 模版 = 生成DOM结构 (Modle + View = DOM)
- 当数据更新,生成新的DOM结构
- 比较新旧DOM结构差异 (input数据更新了)(DOM结构的比较diff 也很消耗性能)
- 然后将差异部分 替换成新的DOM结构
上面的方法虽然改进了,不直接替换DOM少消耗性能了,但是新旧DOM结构的比较也很消耗性能。
再次升级为虚拟DOM的处理:
-
state
数据 -
render
模版 - 数据 + 模版 = 生成DOM结构 (Modle + View = DOM)
- 同时 生成 虚拟DOM 结构 (虽然生成虚拟DOM结构也消耗性能,但是用js生成一个js对象跟生成DOM结构相比,还是节省性能的)
- 当数据更新了,生产新的虚拟DOM结构 (也很快)
- 然后新旧虚拟DOM结构进行差异比较 (两个js对象或者数据比较 性能比 两个DOM结构比较高的多)
- 然后将差异部分进行替换
其实虚拟DOM就是 一个大的js对象或者数组。用js生成一个js对或者,进行两个对象的比较。要比生成一个DOM对象,进行两个DOM结构的比较性能要好的多 。
实际上react的实现:(3,4步是颠倒的)
-
state
数据 -
render
模版 - 数据 + 模版 = 生成 虚拟DOM 结构
- 用 虚拟DOM对象 生成真实的DOM (Modle + View = DOM)
- 当state数据更新了
- 数据 + 模版 = 生成新的虚拟DOM结构 (极大地提升了性能)
- 然后新旧虚拟DOM结构进行差异比较 (两个js对象或者数据比较 性能比 两个DOM结构比较高的多)
- 然后将差异部分进行替换 操作DOM
render () {
// JSX 语法 -> creactElement -> 虚拟DOM(js对象) -> 真实的DOM
return <div><span>item</span></div>
return React.creactElement('div', {}, React.creactElement('span', {}, 'item'))
}
虚拟DOM的优点:
- 性能提升了
- 它使的跨端应用得以实现 React Native (js对象在网页、原生应用也可以识别)
虚拟DOM中的diff算法
第7步 两个虚拟DOM的比对就叫做 diffrence 找步同
思考:什么情况下会进行虚拟DOM的比对,🤔
- 数据更新了(state, props)
- 副组件的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就失去了意义了。