React中的虚拟DOM

当组件当state和props发生变化当时候,组件当render函数就会从新执行,组件就会被从新渲染,react中实现这种从新渲染,他的性能是很是高的,由于他引入了一个虚拟Dom的概念,那么什么是虚拟的Dom,为何虚拟Dom带来了变革性当改变

 

当state发生变化,render函数会从新执行,从新的去渲染一次页面。假设没有react,咱们本身要实现这个功能,那应该怎么去实现呢?咱们来理个思路
1、state 数据
2、jsx模板
3、把数据 + 模板相结合,生成真实的dom,来显示
4、state 发生改变
5、数据 + 模板 结合,生成真实的dom,替换原始的dom
这么作,有一个致命的缺陷,是什么呢?
第一次生成了一个完整的dom片断
第二次生成了一个完整的dom片断
第二次的dom替换第一次的dom,很是耗性能。当咱们inputvalue发生变化的时候,其实页面上只有input这块dom发生变化,若是是这种作法,虽然是input的数据发生变化,可是我须要整个dom区块从新生成一次,替换掉原始的dom状况,这样的话,生成一个完整的dom片断很耗性能,替换掉一个完整的dom片断,也很耗性能。那咱们改良一下

 

1、state 数据
2、jsx模板
3、把数据 + 模板相结合,生成真实的dom,来显示
4、state 发生改变
5、数据 + 模板 结合,生成真实的dom,并不直接替换原始的dom
6、新的dom(DocumentFragment) 和 原始的dom作比对,找差别
7、找出input框发生了变化
8、只用新的dom中的input元素,替换掉老的dom中的input元素
这样的话,是有必定的性能提高的。当新的dom替换掉老的dom的时候,涉及到dom替换的操做或者dom比对的操做,其实是比较耗性能的,因此替换原始的dom耗费了大量的性能。新的作法是什么呢,不替换老的dom,是拿新的dom和原始的dom作对比,只须要更改那一块局部的元素,这样dom替换内容变少了,因此这块性能得以提高,虽然提高了dom替换的性能,可是他又损耗了一部分性能,损耗的性能是哪里呢,损耗的是新的dom要和原有的dom作比对,这样节约了一些性能,又消耗了一些性能,其实在性能的提高上,并非特别明显。因而react提出了虚拟dom的方案



1、state 数据
2、jsx模板
3、把数据 + 模板相结合,生成真实的dom,来显示
  <div id='abc'><span>hello world</span></div>
4、生成虚拟dom(虚拟DOM就是一个js对象,用它来描述真实DOM)
  ['div', {id:'abc'}, ['span', {}, 'hello world']]
  经过这样的一个js对象,咱们就能够表述上面的dom结构了
5、state发生变化
6、数据+模板生成新的虚拟dom(极大的提高了性能)
  ['div', {id:'abc'}, ['span', {}, 'bye bye']]
7、比较原始虚拟DOM和新的虚拟DOM的区别,找到区别是span中的内容(极大的提高了性能) 8、直接操做DOM,改变span中的内容
这种方案相对于上面的方案有什么样的好处,第4步看上去要去另外生成一个虚拟dom,好像还消耗了性能,确实是这样,是有一点性能损耗,用js生成一个js对象,他的代价是很是小的。可是用js生成一个dom元素,他的代价极高,为何呢?底层的原理是,js生成dom会调用webapplication级别的一个api。这种级别的api性能损耗是比较大的。
旧的方案是数据 + 模板 结合,生成真实的dom,而在新的方案里面不是这样的,是数据+模板生成新的虚拟dom,这一步就极大的提高了性能。
旧的方式是新的dom(DocumentFragment) 和 原始的dom作比对。也就是dom层面的作对比,只要是dom层面的对比,他就是很耗性能,新的方式是比较原始虚拟DOM和新的虚拟DOM的区别,两个js对象的比对是很是不消耗性能的
因此虚拟dom是减小了真实dom的建立以及真实dom的对比,取而代之,我建立的都是js对象,对比的也是js对象,用这种方式提高了性能
 
 
为了方便理解,上面写成先生成真实的dom,再生成虚拟dom,实际上这是反过来的,这点要从新的认识一下
1、state 数据
2、jsx模板
3、生成虚拟dom(虚拟DOM就是一个js对象,用它来描述真实DOM)
['div', {id:'abc'}, ['span', {}, 'hello world']]
经过这样的一个js对象,咱们就能够表述上面的dom结构了
4、用虚拟dom的结构,生成真实的dom,来显示
<div id='abc'><span>hello world</span></div>
5、state发生变化
6、新的虚拟dom(极大的提高了性能)
['div', {id:'abc'}, ['span', {}, 'bye bye']]
7、比较原始虚拟DOM和新的虚拟DOM的区别,找到区别是span中的内容(极大的提高了性能)
8、直接操做DOM,改变span中的内容
讲到这里,以前你们会认为jsx就是页面上的dom,但实际上理解原理以后,就知道,他就是一个模板,以后会把这个模板跟state或者props作结合,结合完成以后,有个虚拟dom,有了虚拟dom以后,再生成真实dom。那么jsx的代码和真实的dom有什么样的关系呢?首先,jsx先变成了虚拟dom。也就是js对象。而后再被转化成真实的dom。那么jsx怎么变成js对象呢,js对象you怎么变成真实的dom。

好比 return(<div>item</div>),react底层其实会把jsx语法经过createElement变成js对象,而后再转化真实的dom, return React.createElement('div',{},'item')。这两种效果是一摸同样的。React.createElement是更底层的一个东西,实际上会有一个js对象的东西传递给createElement,那么这个方法实际拿到这个对象以后,直接变成了虚拟dom,而后渲染成真实的dom。因此是
jsx -> createElement -> 虚拟dom(js对象)-> 真实的dom
因此没有jsx,也能够去写页面,可是这样会比较复杂,好比 return(<div><span></span></div>)须要写成 return React.createElement('div',{},React.createElement('span',{},'item'))
因此jsx不是真实的dom,没有这种语法,彻底能够经过createElement实现jsx的功能。jsx之因此存在,是使代码写的方便,简洁。Vue里面也有一个虚拟dom,跟这个也是相似的。

那么虚拟dom带来什么样的好处,只有页面须要渲染的时候,才生成真实的dom。
第一个性能提高了。dom的比对变成了js对象的比对
第二个它使得跨端应用得以实现。你们应该据说过React Native,咱们能够经过React语法写原生的应用,这个得益于虚拟dom的存在,假设没有虚拟dom,一开始就是渲染真实的dom,渲染dom在浏览器上是没有问题的,但是在移动端的原生应用里面,好比安卓或ios机器上的代码的时候,它里面是不存在dom这个概念的,因此没有虚拟dom,在原生的app里面根本没法被使用,因此代码只能在浏览器里面,可是有了虚拟dom就不同了,js对象能够在浏览器里面被识别,同时也能够在原生应用里面被识别,在浏览器里面生成真实的dom,那么在原生应用里面能够不让他生成真实的dom,而是生成原生的组件,这样state,jsx均可以被复用,由于生成的虚拟dom,在哪里均可以运行。这使得react能够开发网页,也能够开发原生应用。
相关文章
相关标签/搜索