Element-ui 2.8.0版本中提升表格性能,做了哪些事情,原理是什么


背景

項目中一直用element-ui,之前用el-table的時候,發現表格數據較多時,滑動表格就會很卡。我們的表格中只有200行數據,每行大概有30的字段,表格滑動就卡的不行。在Element-ui 2.8.0版本中,對表格性能進行了優化,鏈接。短短只有幾行代碼,卻解決了表格的性能問題,今天我們來深度剖析,具體是怎么做到的。

先看改變的代碼

 

 

 代碼很簡單,增加了一個watch,watch中給當前hover的dom增加"hover-row' class,之前的dom移除'hover-row'。並在214行把添加hover-row的代碼去掉了。

聽聽了上面的我說的是不是更蒙了,很正常。那我們在再來看看具體的代碼

 

 

上圖的三段代碼都在element-ui源碼的 packages/table/src/table-body.js中。

如上圖所示,table在渲染時,會調用getRowClass方法,在getRowClass方法中,會判斷當前的行是不是hover的那一行,是的話就增加hover-row這個類。給每一行都增加mouseenter和mouseleave, mouseenter時把vuex中的hoverRow置為當前行,mouseleave時把hoverRow置為空。

問題出在哪?

代碼表面看上去沒有任何問題,但是仔細一想,只要我們把鼠標放在表格上移動,就會觸發mouseenter和mouseleave,vuex中的hoveRow就會發生變化,表格就會重現渲染,render就會重新運行一次。render重新執行一次,getRowStyle有多少行就會執行多少次,getCellStyle和getCellClass(綁在單元格上的方法)有多少個單元格就會執行多少次。假設我們的表格是30*200,那么getRowStyle會執行200次,getCellStyle和getCellClass各執行6000次。還有很多綁在table上的方法都會執行。執行這么多方法,能不卡嗎?

官方怎么解決

 

 首先去掉了添加hover-row的語句。

問題:性能問題出在這里?刪掉這段代碼鼠標移動的時候就不會重新render?

答:問題就出在這里,刪掉這段代碼鼠標移動不會重新render。只要刪掉這段代碼,table reder的時候,this.store.states.hoverRow並不會被touch,鼠標移動的時候this.store.states.hoverRow雖然發生變化,但是並不會觸發頁面的重新渲染,這就是依賴收集的意義。

依賴收集:當 Vue Component render 函數被執行的時候, data 上會被 觸碰(touch), 即被讀, getter 方法會被調用, 此時 Vue 會去記錄此 Vue component 所依賴的所有 data

 

 這時這段代碼就更容易理解了,檢測vuex中hoverRow的變化,通過直接修改dom的方法來添加類名。

問題:不是說操作dom性能不好,為什么這里要直接操作dom

答:首先直接操作dom性能是要優於vdom,因為需要把vdom轉化為真實的dom,但是vdom能夠批量更新,且能跨平台,數據和view分離效率也更高。如果我們只是更新單個數據,且頁面重新reder很復雜時,直接操作dom也是一種解決辦法。當然得看具體情況使用。

我會怎么解決這個問題

如果是我來做,我不會通過js才給一個dom hover增加樣式,因為只用css就能搞定了,明明一段css就能搞定的事,為什么要用js來做

.el-table__body tr:hover {
  background-color: ...;
}

  

 總結

(1)在嵌套循環中,不要用函數,因為每次reder函數都會執行很多遍

(2)善用緩存,善用computed

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM