虚拟DOM

2022-03-14  本文已影响0人  泡杯感冒灵
React引入了虚拟DOM的概念,以提升性能!
React里,当state或者props改变的时候,render函数会重新执行,重新渲染页面。假设没有React,我们该怎么实现这个过程?
  1. state数据
  2. JSX模板
  3. 数据+模板 结合,生成真实的DOM,挂载到页面上显示。
  4. state发生改变。
  5. 数据+模板 结合,生成新的真实的DOM,替换原始的DOM,挂载到页面上展示。

这种方式的缺陷:(生成和替换DOM,会非常耗费性能)
步骤3,第一次生成了一个完整的DOM片段。
步骤5,第二次生成了一个完整的DOM片段。
步骤5,第二次的DOM,替换第一次的DOM。

对上边的方法进行改良
  1. state数据
  2. JSX模板
  3. 数据+模板 结合,生成真实的DOM,挂载到页面上显示。
  4. state发生改变。
  5. 数据+模板 结合,生成真实的DOM,并不直接替换原始的DOM
  6. 新的DOM(这里新的DOM ,就是DocumentFrament 是JS底层的文档碎片,它是在内存里,并没有真实挂载倒页面) 和 原始的DOM做比对,找出差异。
  7. 找到哪些是修改的,有差异的DOM。
  8. 只用新的DOM中的变化的元素,替换掉老的DOM中的元素。

这种方法的缺陷,性能提升并不明细
相比上边直接生成真实DOM并全部替换原始DOM,节约了性能。但是又损耗了一部分性能,那就是新的DOM和原始DOM做比对消化的性能。

虚拟DOM方案
  1. state数据
  2. JSX模板
  3. 数据+模板 结合,生产虚拟DOM(虚拟DOM就是一个JS对象,用它来描述真实DOM)
// 真实DOM节点
<ul id='list'>
  <li class='item'>hello</li>
</ul>

// 虚拟DOM对象
var element = {
  tagName: 'ul', // 节点标签名
  props: { // DOM的属性,用一个对象存储键值对
    id: 'list'
  },
  children: [ // 该节点的子节点
    {tagName: 'li', props: {class: 'item'}, children: ["hello"]},
  ]
}

  1. 用虚拟DOM的结构,生成真实的DOM,挂载到页面上显示。
  2. state发生变化
  3. 数据+模板结合,生成新的虚拟DOM(只生成新的虚拟DOM, 极大提升了性能)
// 新的虚拟DOM
var element = {
  tagName: 'ul', // 节点标签名
  props: { // DOM的属性,用一个对象存储键值对
    id: 'list'
  },
  children: [ // 该节点的子节点
    {tagName: 'li', props: {class: 'item'}, children: ["world"]},
  ]
}
  1. 比较原始虚拟DOM和新的虚拟DOM的区别,找到具体区别,直接操作DOM改变不一样的节点。(对比JS对象,极大提升了性能)

注意,只所以说极大的提升了性能:(用JS创建一个JS对象,并对比JS对象的差异,非常简单,性能代价很小,但是如果要创建一个真实DOM,需要调用Web Application级别的API,这个级别的API,性能损耗非常大)

注意JSX语法,并不是真实的DOM,而是一个模板, 没有JSX语法我们完全可以用React.createElement()来实现同样的功能,只不过比较麻烦。之所以用JSX语法,是因为这种语法,写起来更简洁。
// JSX语法 -> createElement -> 虚拟DOM(JS对象) -> 真实DOM
render(){
        return (
            <div>item</div>
        )
    }

render(){
        return React.createElement('div',{},'item')
    }

虚拟DOM,带来了什么好处?

  1. 性能提升了。
  2. 它使得跨端应用得以实现。React Native (用react语法去写原生应用)。为什么这么说呢,假如没有虚拟DOM,数据发生改变,拿到JSX模板,然后去渲染DOM,这在浏览器上是没有问题的,但是,在移动端的原生应用里,比如安卓或IOS机器上的代码里,是没有DOM的概念的,如果没有虚拟DOM,生成的DOM在原生应用里根本就无法使用。这个时候,我们的代码,只能运行在浏览器里。但是有了虚拟DOM ,因为它是一个JS对象,这个对象,在浏览器里和在原生应用里,都可以被识别。只不过,在浏览器里,虚拟dom用来生成真实DOM,在原生应用里,用来生成原生组件,所以,state和JSX模板,都可以被复用。所以,React即可以开发网页应用,又可以开发原生应用。
虚拟DOM中的Diff算法
上一篇下一篇

猜你喜欢

热点阅读