偷懶不可取:React中DOM

原由

初出茅廬的我一猛子扎進React的海洋,掙扎的過程當中可謂使勁渾身解數,只要是React文檔中有提到過的,無所不用其極。最後,在前輩的薰陶還有編寫項目和自我學習中,規範性也愈來愈強,思路也愈來愈清晰——狗刨終於進化成自由泳。
這篇文章中呢,原由就是在實現一些需求的時候,通篇React語法中加入了古老的DOM讀寫,而後就被老大批評了。青少年最不缺的就是銳氣和鑽研精神,哈哈,沒錯,寫這篇文章最大的緣由就是——我不服~
爲啥不讓我用DOM?DOM有什麼很差?React很難實現的需求應該怎麼作?html

結果

沒錯,結果就是——服。在經歷許多代碼重構和邏輯修改後,發現React中有個DOM從視覺上感受就有些不爽,不加上註釋或者即便加上註釋都給人一種不知所謂的感受,維護上也有很大難度,好比前端

if (this.tableIsOpen) { // 表格自展開
  setTimeout(() => {
    const openClick = document.querySelectorAll('.testToggle');
    for (let i = 0; i < openClick.length; i += 1) {
      openClick[i].click();
    }
  }, 10);
}

固然最主要的是性能,由於React在DOM二次渲染時的效率會比原生DOM的效率高的多,因此會有更好的方式去解決。下面就來具體的說一下。node

過程

用DOM的場景

一、在已有組件的基礎上,待組件渲染完成後,調用其內部的方法。好比uxcore-table實現二級表格自展開時,須要調用組件元素中綁定的toggleSubComp(rowData)
二、DOM獲取document.body.className來判斷國際化環境是否爲中文。
三、多個組件,一個組件的狀態須要保持不變,可是其餘組件須要根據交互來改變狀態。例如react

<Father>
    <brother>
        <child></child>
    </brother>
    <notChange></notChange>
</Father>

可優化方案

1

首先說第三個場景,說到改變狀態固然就是statesetState,那麼順着這個思路走的話,好的,分割好每一個組件,各個組件的方法最好不能有交叉。
然並卵,一旦各個組件之間有了交互上的關聯,狀態改變條件互相依賴,即便讓各類props穿插傳遞狀態條件,可是,props的變化對於須要接收它的組件,componentWillReceiveProps(nextprops)在父級有變化(setState)時,纔會接收新的props。完蛋,又回到原點,須要保持狀態不變又與須要變化的組件有交互關聯的仍是要被setState影響。
因此,用DOM吧。。。可是,用DOM修改元素,是很影響性能的,下個小結會說。其實這個思路其實並無錯,這個時候就要用到react專門爲一些特殊狀況準備的refs,官方文檔上說:ref添加到Compoennt上獲取的是Compoennt實例,添加到原生HTML上獲取的是DOM瀏覽器

When attaching a ref to a DOM component like <div />, you get the DOM node back; when attaching a ref to a composite component like <TextInput />, you'll get the React class instance. In the latter case, you can call methods on that component if any are exposed in its class definition.

這個意思,就是我在本身的class xxx extends React.Component的組件上加上refs中,獲取的是虛擬DOM節點(ReactElement),那麼,就好說了,不再用亂搞一氣的props還有原生DOM的一堆改變樣式的操做,在組件內部寫方法,而後根據父級狀態條件,利用this.refs.xxx.fn(status)調用便可。框架

2

第二個場景,我的感受並無影響到性能,畢竟React的組件在<script></script>標籤中,瀏覽器解析html的時候,在React的組件加載前,<body></body>元素已經存在,單純的查詢DOM不會致使頁面的重寫和迴流。因此我的認爲,React中仍是能夠少許用一些無關痛癢的DOM(我會說我仍是鍾愛原生DOM嗎)。性能

3

第一個場景,最開始舉的例子。用於componentDidMount中,哈哈,死循環——在展開二級表格時不斷的重新渲染繼而不斷調用該方法,那麼用在componentDidUpdate中就能夠了,可是爲何要用定時器呢,由於在元素節點所有渲染出來時,只會在最後一個元素執行點擊事件,用refs也是同樣的。
目前尚未找到緣由,探索中。。。若是有大大知道,能夠告訴我啊~不勝感激^ο^學習

DOM影響React性能分析

對於性能的影響,很明顯了,就是多餘的DOM計算。既然React用的虛擬DOM形式,再用DOM去修改,那麼,瀏覽器再計算所有React的更改後,再去計算一遍原生DOM修改,這就很是尷尬了,React還不如不去用,也沒有節約多少時間。
再次總體用React中穿插DOM看着也不是很美觀。優化

總結

在應用一個框架的時候,那麼,咱們不但要理解它的思想,還要嚴格的執行它,固然這個思想必須是正確的,高效的。好比React的虛擬DOM,就要在虛擬DOM中操做。
若是代碼不遵循它的思想,那麼就至關於不認可這個框架,這種衝突若是出現,要麼重構代碼,要麼就摒棄這個框架。
以上是本人這個小前端的一點經驗和淺見,但願你們給予指正~this

相關文章
相關標籤/搜索