加入收藏 | 设为首页 | 会员中心 | 我要投稿 牡丹江站长网 (https://www.0453zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 运营中心 > 建站资源 > 优化 > 正文

深入理解React的Virtual DOM

发布时间:2019-04-25 10:12:51 所属栏目:优化 来源:Choerodon
导读:React在前端界一直很流行,而且学起来也不是很难,只需要学会JSX、理解State和Props,然后就可以愉快的玩耍了,但想要成为React的专家你还需要对React有一些更深入的理解,希望本文对你有用。 这是Choerodon的一个前端页面 在复杂的前端项目中一个页面可能

为此,开发者需要使用ReactDOM库及其render方法:

  1. function Table({ rows }) { /* ... */ } // 组件定义  
  2. // 渲染一个组件  
  3. ReactDOM.render(  
  4.   React.createElement(Table, { rows: rows }), // "创建" 一个 component  
  5.   document.getElementById('#root') // 将它放入DOM中  
  6. ); 

当ReactDOM.render被调用时,React.createElement最终也会被调用,它返回以下对象:

  1. // 这个对象里还有很多其他的字段,但现在对开发者来说重要的是这些。  
  2. {  
  3.   type: Table,  
  4.   props: {  
  5.     rows: rows  
  6.   },  
  7.   // ...  

这些对象构成了React意义上的Virtual DOM

它们将在所有进一步渲染中相互比较,并最终转换为真正的DOM(与Virtual DOM对比)。

这是另一个例子:这次有一个div具有class属性和几个子节点:

  1. React.createElement(  
  2.   'div',  
  3.   { className: 'cn' },  
  4.   'Content 1!',  
  5.   'Content 2!',  
  6. ); 

变成:

  1. {  
  2.   type: 'div',  
  3.   props: {  
  4.     className: 'cn',  
  5.     children: [  
  6.       'Content 1!',  
  7.       'Content 2!'  
  8.     ]  
  9.   }  

所有的传入的展开函数,也就是React.createElement除了第一第二个参数剩下的参数都会在props对象中的children属性中,不管传入的是什么函数,他们最终都会作为children传入props中。

而且,开发者可以直接在JSX代码中添加children属性,将子项直接放在children中,结果仍然是相同的:

  1. <div className='cn' children={['Content 1!', 'Content 2!']} /> 

在Virtual DOM对象被建立出来之后ReactDOM.render会尝试按以下规则把它翻译成浏览器能够看得懂的DOM节点:

  •  如果Virtual DOM对象中的type属性是一个string类型的tag名称,就创建一个tag,包含props里的全部属性。
  •  如果Virtual DOM对象中的type属性是一个函数或者class,就调用它,它返回的可能还是一个Virtual DOM然后将结果继续递归调用此过程。
  •  如果props中有children属性,就对children中的每个元素进行以上过程,并将返回的结果放到父DOM节点中。

最后,浏览器获得了以下HTML(对于上述table的例子):

  1. <table>  
  2.   <tr>  
  3.     <td>Title</td>  
  4.   </tr>  
  5.   ...  
  6. </table> 

重建DOM

接下浏览器要“重建”一个DOM节点,如果浏览器要更新一个页面,显然,开发者并不希望替换页面中的全部元素,这就是React真正的魔法了。如何才能实现它?先从最简单的方法开始,重新调用这个节点的ReactDOM.render方法。

  1. // 第二次调用  
  2. ReactDOM.render(  
  3.   React.createElement(Table, { rows: rows }),  
  4.   document.getElementById('#root')  
  5. ); 

这一次,上面的代码执行逻辑将与看到的代码不同。React不是从头开始创建所有DOM节点并将它们放在页面上,React将使用“diff”算法,以确定节点树的哪些部分必须更新,哪些部分可以保持不变。

那么它是怎样工作的?只有少数几个简单的情况,理解它们将对React程序的优化有很大帮助。请记住,接下来看到的对象是用作表示React Virtual DOM中节点的对象。

▌Case 1:type是一个字符串,type在调用之间保持不变,props也没有改变。

  1. // before update  
  2. { type: 'div', props: { className: 'cn' } }  
  3. // after update  
  4. { type: 'div', props: { className: 'cn' } } 

这是最简单的情况:DOM保持不变。

(编辑:牡丹江站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!