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 功能类似,都可以通过传参来查找指定父元素

猜你喜欢

转载自www.cnblogs.com/sinosaurus/p/12982207.html
今日推荐