tab切換引起瀏覽器卡頓


tab切換引起瀏覽器卡頓

最近寫了基於 index 索引關聯進行切換的tab組件,誰知道頻繁點擊后,幾個瀏覽器都卡死,連查看 performance 都看不了。在嘗試幾次后,沒能在 chrome 的 performance下看到原因,因為卡的動不了。反而在 firefox 下看到原因了。

本地代碼業務邏輯大致如下

<!-- tab header -->
<div data-type="one"><button>one</button></div>
<div data-type="two"><button>two</button></div>
<div data-type="three"><button>three</button></div>
<!-- tab content -->
<components :is="type"></components>

通過上面按鈕點擊,動態更改type,從而更新組件。但是由於點擊時,不一定點擊的是 div,有可能是 button,因而無論點擊哪一個都需要找到div,拿到data-type的參數。於是自己便寫了一個查找父元素的function。

  function findTargetByClassNameAndTarget (target = {}, className = '') {
      let el = target
      while (!el.classList.contains(className) && el) {
        el = target.parentNode
      }
      return el
    }

初步點擊時,並沒有任何問題,都能及時響應,但是快速頻繁之后就開始。firefox顯示這段js一直在運行。我也是醉了。於是換成了下面這樣的才得以解決。

  function closest (ele, selector) {
      const matches = ele.matches 
			|| ele.webkitMatchesSelector
			|| ele.mozMatchesSelector
			|| ele.msMatchesSelector
      if (matches) {
        while (ele) {
          if (matches.call(ele, selector)) {
            return ele
          } else {
            ele = ele.parentNode
          }
        }
      }
      return null
    }

思考

之前為了解決上訴問題,以為是頻繁地更新DOM,導致頁面重繪重排,從而性能有了影響。但是 el-tab 卻沒有。看了下代碼沒有找到明顯的優化之處。然后嘗試給 點擊事件加延遲,componentkeep-alive。一樣沒有效果。因而以為是不是使用 v-if 導致的。切換為v-show進行處理依舊沒有效果。參考網上做法,開啟硬件加速 transform: translateZ(0) 依舊沒有任何效果,反而還引發其他問題(彈框的fixed定位不准)

因為tab切換引起的性能問題,網上有很多,我個人覺得這兩個將來值得借鑒一二,原理都是 dom 更新完再進行。

  1. 加一個開發,在dom更新完后再進行下一步

    <div id="first" v-if="flag"></div>
    <div id="last" v-else></div>
    <script>
    	...
    	function handleTab () {
    	 if (this.flag) {
           first.show()
           last.hide()
    	   this.flag = false
         } else {
    	  first.hide()
    	  last.show()
    	   this.flag = true
          }
    	}
    	...
    </script>
    
  2. 使用 vueupdate 來進行處理。因為 updated 也是 dom 更新完再執行

針對上面的代碼,嘗試了之前寫的另一種方式

   function findElementUpward (el, className) {
      let parent = el
      let name = Array.from(parent.classList || [])
      while (parent && (!name.length || !name.includes(className))) {
        parent = parent.parentNode
        if (parent) name = Array.from(parent.classList || [])
      }
      return parent
    }

依舊是沒問題。因而對比兩者的差距,只是這次取巧使用了自帶的 contains 這個方法而已,卻沒想到導致這么大的問題。只是目前還無法判斷是不是這個 contains 導致的性能問題。需要找個方式進行研究一下方可。

  • matchesclosest 功能類似,都可以通過傳參來查找指定父元素


免責聲明!

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



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