背景
使用 vue + element UI 进行组件(Tabs)操作,重写了部分的 tabs 组件的样式
复现地址
https://codepen.io/meetthebest/pen/jOyMQLV
复现操作
点击页面的 add tab 按钮,预计点击6次左右,页面将卡死
有大佬知道是什么问题导致的吗 ? 个人排查过程中,发现如下图中的 width 属性注释或者删除了,就不会卡死🤔
目前还没找到问题,希望知道的大佬指导一下,感谢!!!
神奇,看js也没卡死,如果楼主解决了记得@我下
感觉上不是 js 死循环了,而是绘制 dom 的时候卡住了,比如卡住的时候在控制台执行 document.body.append('<b>Hello world!</b>')
是没反应的,但是敲 console.log('hello')
是可以的
我猜测你的加 tab 逻辑里是不是会不停触发 dom 的重绘,导致页面卡住
vue里面的代码一直在递归调用,看起来像是框架的bug。
先把控制台切换到CodePen(jOyMQLV)
等卡住的时候按下 F8
暂停js,然后随便抛一个什么东西出来,就可以在控制台看到一个超长的调用堆栈。
throw 123
VM75:1 Uncaught 123
eval @ VM75:1
flushSchedulerQueue @ vue.js:4300
(anonymous) @ vue.js:1989
flushCallbacks @ vue.js:1915
Promise.then (async)
timerFunc @ vue.js:1942
nextTick @ vue.js:1999
queueWatcher @ vue.js:4403
update @ vue.js:4543
notify @ vue.js:745
reactiveSetter @ vue.js:1070
proxySetter @ vue.js:4630
update @ index.js:1
updated @ index.js:1
invokeWithErrorHandling @ vue.js:1863
callHook @ vue.js:4220
callUpdatedHooks @ vue.js:4352
flushSchedulerQueue @ vue.js:4337
(anonymous) @ vue.js:1989
flushCallbacks @ vue.js:1915
Promise.then (async)
timerFunc @ vue.js:1942
nextTick @ vue.js:1999
queueWatcher @ vue.js:4403
update @ vue.js:4543
notify @ vue.js:745
reactiveSetter @ vue.js:1070
proxySetter @ vue.js:4630
update @ index.js:1
updated @ index.js:1
invokeWithErrorHandling @ vue.js:1863
callHook @ vue.js:4220
callUpdatedHooks @ vue.js:4352
flushSchedulerQueue @ vue.js:4337
(anonymous) @ vue.js:1989
flushCallbacks @ vue.js:1915
Promise.then (async)
timerFunc @ vue.js:1942
nextTick @ vue.js:1999
queueWatcher @ vue.js:4403
update @ vue.js:4543
notify @ vue.js:745
reactiveSetter @ vue.js:1070
proxySetter @ vue.js:4630
update @ index.js:1
updated @ index.js:1
invokeWithErrorHandling @ vue.js:1863
callHook @ vue.js:4220
callUpdatedHooks @ vue.js:4352
flushSchedulerQueue @ vue.js:4337
(anonymous) @ vue.js:1989
flushCallbacks @ vue.js:1915
Promise.then (async)
timerFunc @ vue.js:1942
nextTick @ vue.js:1999
queueWatcher @ vue.js:4403
update @ vue.js:4543
notify @ vue.js:745
reactiveSetter @ vue.js:1070
proxySetter @ vue.js:4630
update @ index.js:1
updated @ index.js:1
invokeWithErrorHandling @ vue.js:1863
callHook @ vue.js:4220
callUpdatedHooks @ vue.js:4352
flushSchedulerQueue @ vue.js:4337
(anonymous) @ vue.js:1989
flushCallbacks @ vue.js:1915
Promise.then (async)
timerFunc @ vue.js:1942
nextTick @ vue.js:1999
queueWatcher @ vue.js:4403
update @ vue.js:4543
notify @ vue.js:745
reactiveSetter @ vue.js:1070
proxySetter @ vue.js:4630
update @ index.js:1
updated @ index.js:1
invokeWithErrorHandling @ vue.js:1863
callHook @ vue.js:4220
callUpdatedHooks @ vue.js:4352
flushSchedulerQueue @ vue.js:4337
(anonymous) @ vue.js:1989
flushCallbacks @ vue.js:1915
Promise.then (async)
timerFunc @ vue.js:1942
nextTick @ vue.js:1999
queueWatcher @ vue.js:4403
update @ vue.js:4543
notify @ vue.js:745
reactiveSetter @ vue.js:1070
proxySetter @ vue.js:4630
update @ index.js:1
updated @ index.js:1
invokeWithErrorHandling @ vue.js:1863
callHook @ vue.js:4220
callUpdatedHooks @ vue.js:4352
flushSchedulerQueue @ vue.js:4337
(anonymous) @ vue.js:1989
flushCallbacks @ vue.js:1915
Promise.then (async)
timerFunc @ vue.js:1942
nextTick @ vue.js:1999
queueWatcher @ vue.js:4403
update @ vue.js:4543
notify @ vue.js:745
reactiveSetter @ vue.js:1070
proxySetter @ vue.js:4630
update @ index.js:1
updated @ index.js:1
invokeWithErrorHandling @ vue.js:1863
callHook @ vue.js:4220
callUpdatedHooks @ vue.js:4352
flushSchedulerQueue @ vue.js:4337
(anonymous) @ vue.js:1989
flushCallbacks @ vue.js:1915
Promise.then (async)
timerFunc @ vue.js:1942
nextTick @ vue.js:1999
queueWatcher @ vue.js:4403
update @ vue.js:4543
notify @ vue.js:745
reactiveSetter @ vue.js:1070
proxySetter @ vue.js:4630
update @ index.js:1
updated @ index.js:1
invokeWithErrorHandling @ vue.js:1863
callHook @ vue.js:4220
callUpdatedHooks @ vue.js:4352
flushSchedulerQueue @ vue.js:4337
(anonymous) @ vue.js:1989
flushCallbacks @ vue.js:1915
Promise.then (async)
timerFunc @ vue.js:1942
nextTick @ vue.js:1999
queueWatcher @ vue.js:4403
update @ vue.js:4543
notify @ vue.js:745
reactiveSetter @ vue.js:1070
proxySetter @ vue.js:4630
update @ index.js:1
updated @ index.js:1
invokeWithErrorHandling @ vue.js:1863
callHook @ vue.js:4220
callUpdatedHooks @ vue.js:4352
flushSchedulerQueue @ vue.js:4337
(anonymous) @ vue.js:1989
flushCallbacks @ vue.js:1915
Promise.then (async)
timerFunc @ vue.js:1942
nextTick @ vue.js:1999
queueWatcher @ vue.js:4403
update @ vue.js:4543
notify @ vue.js:745
reactiveSetter @ vue.js:1070
proxySetter @ vue.js:4630
update @ index.js:1
updated @ index.js:1
invokeWithErrorHandling @ vue.js:1863
callHook @ vue.js:4220
callUpdatedHooks @ vue.js:4352
flushSchedulerQueue @ vue.js:4337
(anonymous) @ vue.js:1989
flushCallbacks @ vue.js:1915
Promise.then (async)
timerFunc @ vue.js:1942
nextTick @ vue.js:1999
queueWatcher @ vue.js:4403
update @ vue.js:4543
notify @ vue.js:745
reactiveSetter @ vue.js:1070
proxySetter @ vue.js:4630
update @ index.js:1
updated @ index.js:1
invokeWithErrorHandling @ vue.js:1863
callHook @ vue.js:4220
callUpdatedHooks @ vue.js:4352
flushSchedulerQueue @ vue.js:4337
(anonymous) @ vue.js:1989
flushCallbacks @ vue.js:1915
Promise.then (async)
timerFunc @ vue.js:1942
nextTick @ vue.js:1999
queueWatcher @ vue.js:4403
update @ vue.js:4543
notify @ vue.js:745
reactiveSetter @ vue.js:1070
proxySetter @ vue.js:4630
update @ index.js:1
updated @ index.js:1
invokeWithErrorHandling @ vue.js:1863
callHook @ vue.js:4220
callUpdatedHooks @ vue.js:4352
flushSchedulerQueue @ vue.js:4337
(anonymous) @ vue.js:1989
flushCallbacks @ vue.js:1915
Promise.then (async)
timerFunc @ vue.js:1942
nextTick @ vue.js:1999
queueWatcher @ vue.js:4403
update @ vue.js:4543
notify @ vue.js:745
reactiveSetter @ vue.js:1070
proxySetter @ vue.js:4630
update @ index.js:1
updated @ index.js:1
invokeWithErrorHandling @ vue.js:1863
callHook @ vue.js:4220
callUpdatedHooks @ vue.js:4352
flushSchedulerQueue @ vue.js:4337
(anonymous) @ vue.js:1989
flushCallbacks @ vue.js:1915
Promise.then (async)
timerFunc @ vue.js:1942
nextTick @ vue.js:1999
queueWatcher @ vue.js:4403
update @ vue.js:4543
notify @ vue.js:745
reactiveSetter @ vue.js:1070
proxySetter @ vue.js:4630
update @ index.js:1
updated @ index.js:1
invokeWithErrorHandling @ vue.js:1863
callHook @ vue.js:4220
callUpdatedHooks @ vue.js:4352
flushSchedulerQueue @ vue.js:4337
(anonymous) @ vue.js:1989
flushCallbacks @ vue.js:1915
Promise.then (async)
timerFunc @ vue.js:1942
nextTick @ vue.js:1999
queueWatcher @ vue.js:4403
update @ vue.js:4543
notify @ vue.js:745
reactiveSetter @ vue.js:1070
proxySetter @ vue.js:4630
update @ index.js:1
updated @ index.js:1
invokeWithErrorHandling @ vue.js:1863
callHook @ vue.js:4220
callUpdatedHooks @ vue.js:4352
flushSchedulerQueue @ vue.js:4337
(anonymous) @ vue.js:1989
flushCallbacks @ vue.js:1915
Promise.then (async)
timerFunc @ vue.js:1942
nextTick @ vue.js:1999
queueWatcher @ vue.js:4403
update @ vue.js:4543
notify @ vue.js:745
reactiveSetter @ vue.js:1070
proxySetter @ vue.js:4630
update @ index.js:1
updated @ index.js:1
invokeWithErrorHandling @ vue.js:1863
callHook @ vue.js:4220
callUpdatedHooks @ vue.js:4352
flushSchedulerQueue @ vue.js:4337
(anonymous) @ vue.js:1989
flushCallbacks @ vue.js:1915
Promise.then (async)
timerFunc @ vue.js:1942
nextTick @ vue.js:1999
queueWatcher @ vue.js:4403
update @ vue.js:4543
notify @ vue.js:745
reactiveSetter @ vue.js:1070
proxySetter @ vue.js:4630
update @ index.js:1
updated @ index.js:1
invokeWithErrorHandling @ vue.js:1863
callHook @ vue.js:4220
callUpdatedHooks @ vue.js:4352
flushSchedulerQueue @ vue.js:4337
(anonymous) @ vue.js:1989
flushCallbacks @ vue.js:1915
Promise.then (async)
timerFunc @ vue.js:1942
nextTick @ vue.js:1999
queueWatcher @ vue.js:4403
update @ vue.js:4543
notify @ vue.js:745
reactiveSetter @ vue.js:1070
proxySetter @ vue.js:4630
update @ index.js:1
updated @ index.js:1
invokeWithErrorHandling @ vue.js:1863
callHook @ vue.js:4220
callUpdatedHooks @ vue.js:4352
flushSchedulerQueue @ vue.js:4337
(anonymous) @ vue.js:1989
flushCallbacks @ vue.js:1915
Promise.then (async)
timerFunc @ vue.js:1942
nextTick @ vue.js:1999
queueWatcher @ vue.js:4403
update @ vue.js:4543
notify @ vue.js:745
reactiveSetter @ vue.js:1070
proxySetter @ vue.js:4630
update @ index.js:1
updated @ index.js:1
invokeWithErrorHandling @ vue.js:1863
callHook @ vue.js:4220
callUpdatedHooks @ vue.js:4352
flushSchedulerQueue @ vue.js:4337
(anonymous) @ vue.js:1989
flushCallbacks @ vue.js:1915
Promise.then (async)
timerFunc @ vue.js:1942
nextTick @ vue.js:1999
queueWatcher @ vue.js:4403
update @ vue.js:4543
notify @ vue.js:745
reactiveSetter @ vue.js:1070
proxySetter @ vue.js:4630
update @ index.js:1
updated @ index.js:1
invokeWithErrorHandling @ vue.js:1863
callHook @ vue.js:4220
callUpdatedHooks @ vue.js:4352
flushSchedulerQueue @ vue.js:4337
(anonymous) @ vue.js:1989
flushCallbacks @ vue.js:1915
Promise.then (async)
timerFunc @ vue.js:1942
nextTick @ vue.js:1999
queueWatcher @ vue.js:4403
update @ vue.js:4543
notify @ vue.js:745
reactiveSetter @ vue.js:1070
proxySetter @ vue.js:4630
update @ index.js:1
updated @ index.js:1
invokeWithErrorHandling @ vue.js:1863
callHook @ vue.js:4220
callUpdatedHooks @ vue.js:4352
flushSchedulerQueue @ vue.js:4337
(anonymous) @ vue.js:1989
flushCallbacks @ vue.js:1915
Promise.then (async)
timerFunc @ vue.js:1942
nextTick @ vue.js:1999
queueWatcher @ vue.js:4403
update @ vue.js:4543
notify @ vue.js:745
reactiveSetter @ vue.js:1070
proxySetter @ vue.js:4630
update @ index.js:1
updated @ index.js:1
invokeWithErrorHandling @ vue.js:1863
callHook @ vue.js:4220
callUpdatedHooks @ vue.js:4352
flushSchedulerQueue @ vue.js:4337
(anonymous) @ vue.js:1989
flushCallbacks @ vue.js:1915
Promise.then (async)
timerFunc @ vue.js:1942
nextTick @ vue.js:1999
queueWatcher @ vue.js:4403
update @ vue.js:4543
notify @ vue.js:745
reactiveSetter @ vue.js:1070
proxySetter @ vue.js:4630
update @ index.js:1
updated @ index.js:1
invokeWithErrorHandling @ vue.js:1863
callHook @ vue.js:4220
callUpdatedHooks @ vue.js:4352
flushSchedulerQueue @ vue.js:4337
(anonymous) @ vue.js:1989
flushCallbacks @ vue.js:1915
Promise.then (async)
timerFunc @ vue.js:1942
nextTick @ vue.js:1999
queueWatcher @ vue.js:4403
update @ vue.js:4543
notify @ vue.js:745
reactiveSetter @ vue.js:1070
proxySetter @ vue.js:4630
update @ index.js:1
updated @ index.js:1
invokeWithErrorHandling @ vue.js:1863
callHook @ vue.js:4220
callUpdatedHooks @ vue.js:4352
flushSchedulerQueue @ vue.js:4337
(anonymous) @ vue.js:1989
flushCallbacks @ vue.js:1915
Promise.then (async)
timerFunc @ vue.js:1942
nextTick @ vue.js:1999
queueWatcher @ vue.js:4403
update @ vue.js:4543
notify @ vue.js:745
reactiveSetter @ vue.js:1070
proxySetter @ vue.js:4630
update @ index.js:1
updated @ index.js:1
invokeWithErrorHandling @ vue.js:1863
callHook @ vue.js:4220
callUpdatedHooks @ vue.js:4352
flushSchedulerQueue @ vue.js:4337
(anonymous) @ vue.js:1989
flushCallbacks @ vue.js:1915
Promise.then (async)
timerFunc @ vue.js:1942
nextTick @ vue.js:1999
queueWatcher @ vue.js:4403
update @ vue.js:4543
notify @ vue.js:745
reactiveSetter @ vue.js:1070
proxySetter @ vue.js:4630
update @ index.js:1
updated @ index.js:1
invokeWithErrorHandling @ vue.js:1863
callHook @ vue.js:4220
callUpdatedHooks @ vue.js:4352
flushSchedulerQueue @ vue.js:4337
(anonymous) @ vue.js:1989
flushCallbacks @ vue.js:1915
Promise.then (async)
timerFunc @ vue.js:1942
nextTick @ vue.js:1999
queueWatcher @ vue.js:4403
update @ vue.js:4543
notify @ vue.js:745
reactiveSetter @ vue.js:1070
proxySetter @ vue.js:4630
update @ index.js:1
updated @ index.js:1
invokeWithErrorHandling @ vue.js:1863
callHook @ vue.js:4220
callUpdatedHooks @ vue.js:4352
flushSchedulerQueue @ vue.js:4337
(anonymous) @ vue.js:1989
flushCallbacks @ vue.js:1915
Promise.then (async)
timerFunc @ vue.js:1942
nextTick @ vue.js:1999
queueWatcher @ vue.js:4403
update @ vue.js:4543
notify @ vue.js:745
reactiveSetter @ vue.js:1070
proxySetter @ vue.js:4630
update @ index.js:1
updated @ index.js:1
invokeWithErrorHandling @ vue.js:1863
callHook @ vue.js:4220
callUpdatedHooks @ vue.js:4352
flushSchedulerQueue @ vue.js:4337
(anonymous) @ vue.js:1989
flushCallbacks @ vue.js:1915
Promise.then (async)
timerFunc @ vue.js:1942
nextTick @ vue.js:1999
queueWatcher @ vue.js:4403
update @ vue.js:4543
notify @ vue.js:745
reactiveSetter @ vue.js:1070
proxySetter @ vue.js:4630
update @ index.js:1
updated @ index.js:1
invokeWithErrorHandling @ vue.js:1863
callHook @ vue.js:4220
callUpdatedHooks @ vue.js:4352
flushSchedulerQueue @ vue.js:4337
(anonymous) @ vue.js:1989
flushCallbacks @ vue.js:1915
Promise.then (async)
timerFunc @ vue.js:1942
nextTick @ vue.js:1999
queueWatcher @ vue.js:4403
update @ vue.js:4543
notify @ vue.js:745
reactiveSetter @ vue.js:1070
proxySetter @ vue.js:4630
update @ index.js:1
updated @ index.js:1
invokeWithErrorHandling @ vue.js:1863
callHook @ vue.js:4220
callUpdatedHooks @ vue.js:4352
flushSchedulerQueue @ vue.js:4337
(anonymous) @ vue.js:1989
flushCallbacks @ vue.js:1915
Promise.then (async)
timerFunc @ vue.js:1942
nextTick @ vue.js:1999
queueWatcher @ vue.js:4403
update @ vue.js:4543
notify @ vue.js:745
reactiveSetter @ vue.js:1070
proxySetter @ vue.js:4630
update @ index.js:1
updated @ index.js:1
invokeWithErrorHandling @ vue.js:1863
callHook @ vue.js:4220
callUpdatedHooks @ vue.js:4352
flushSchedulerQueue @ vue.js:4337
(anonymous) @ vue.js:1989
flushCallbacks @ vue.js:1915
Promise.then (async)
timerFunc @ vue.js:1942
nextTick @ vue.js:1999
queueWatcher @ vue.js:4403
update @ vue.js:4543
notify @ vue.js:745
reactiveSetter @ vue.js:1070
proxySetter @ vue.js:4630
update @ index.js:1
updated @ index.js:1
invokeWithErrorHandling @ vue.js:1863
callHook @ vue.js:4220
callUpdatedHooks @ vue.js:4352
flushSchedulerQueue @ vue.js:4337
(anonymous) @ vue.js:1989
flushCallbacks @ vue.js:1915
把 important 的优先取消掉,提级操作过多其实很耗计算的。
以为是标题党
@yuanliwei 其实还没不是太明白,为何会引起 Vue 的内部递归,可是如果注释了那 width 属性,又为啥可以了
这样就下出css的结论?明显就是js问题嘛,肯定是哪段逻辑和宽度有关没处理对或者就没考虑你这种情况
@linlifengx 老哥,demo 是从饿了么那么直接拿来的(饿了么: https://codepen.io/pen/ ),你可以把前面有问题的地址的css 复制进行,就能重现。
至于具体啥问题,这个确实我没有头绪😞~ 只能望各位大佬解惑。
问题原因:width: 100%!important;
放在了 .is-scrollable
下面,element-ui
会在tab
中的内容宽度超出自身宽度的时候动态添加.is-scrollable
,因此出现死循环、
具体流程如下:
tab
中内容宽度超出自身宽度
element-ui
给tab
添加了一个.is-scrollable
此时width: 100%!important;
起作用了,tab
内容的宽度被设置为tab
的宽度
然后element-ui
把.is-scrollable
移除
tab
中内容宽度超出自身宽度
element-ui
给tab
添加了一个.is-scrollable
此时width: 100%!important;
起作用了,tab
内容的宽度被设置为tab
的宽度
然后element-ui
把.is-scrollable
移除
tab
中内容宽度超出自身宽度
element-ui
给tab
添加了一个.is-scrollable
此时width: 100%!important;
起作用了,tab
内容的宽度被设置为tab
的宽度
然后element-ui
把.is-scrollable
移除
tab
中内容宽度超出自身宽度
element-ui
给tab
添加了一个.is-scrollable
此时width: 100%!important;
起作用了,tab
内容的宽度被设置为tab
的宽度
然后element-ui
把.is-scrollable
移除
tab
中内容宽度超出自身宽度
…
@yuanliwei 盲猜也是element-ui动态调整css陷入死循环了,不过没找到对应代码
代码从调用堆栈点过去就是了
@yuanliwei 看样子应该是加了 width 和框架内部发生了 死循环了。 感谢大佬解惑哈👍
mark,学习了!