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
却没有。看了下代码没有找到明显的优化之处。然后尝试给 点击事件加延迟,component
加 keep-alive
。一样没有效果。因而以为是不是使用 v-if
导致的。切换为v-show
进行处理依旧没有效果。参考网上做法,开启硬件加速 transform: translateZ(0)
依旧没有任何效果,反而还引发其他问题(弹框的fixed定位不准)
因为tab切换引起的性能问题,网上有很多,我个人觉得这两个将来值得借鉴一二,原理都是 dom
更新完再进行。
-
加一个开发,在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>
-
使用
vue
的update
来进行处理。因为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
导致的性能问题。需要找个方式进行研究一下方可。