被偷家了!崩溃!!Element-plus组件测试的后续~

7,685 阅读4分钟

image.png

最新消息,VUE的slot移除产生内存泄漏问题已修复!!!前端佬们嗨起来~

dky9N7ZqowThEwulM3PNhAnzouC1iPWI.gif

---------------------分割线-------------------------------

这个是之前一个文章的后续,没有看过的前端佬可以点这里看看~

致歉

首先,向前端佬们说声,对不起!

image.png

怪自己学艺不精,没有仔细斟酌,上一篇文章里有一些错误,必须在这里指出来!

造成错误的原因有两个,Devtools问题和VUE的slots的问题,没有看过之前的前端佬也没有关系,因为这个关乎很多前端佬的测试。以下为详情。

Devtools工具的BUG

Devtools的问题,是通过Chromium issues中知道的。有条件的前端佬可以戳这里。 没有条件的,我这里借花献佛说明下。比如下面这个例子:

<!DOCTYPE html>
<html>
<head>
    <title>方块从左到右动画</title>
    <style>
        .square {
            width: 50px;
            height: 50px;
            background-color: red;
            /* 你可以修改颜色 */
            position: absolute;
            /* 关键:使用 absolute 或 fixed 定位,方便移动 */
            top: 50px;
            /* 初始垂直位置,可以调整 */
            left: 0;
            /* 初始水平位置,从左边开始 */
            animation: moveRight 2s linear infinite;
            /* 应用动画 */
        }
        @keyframes moveRight {
            from {
                transform: translateX(0);
                /* 动画起始位置:不位移 */
            }

            to {
                transform: translateX(200px);
                /* 动画结束位置:向右移动 200px,可以调整 */
            }
        }
        /* 添加暂停动画的类 */
        .animation-paused {
            animation-play-state: paused;
        }
    </style>
</head>
<body>
    <div id="animatedSquare" class="square"></div>
    <button id="removeButton">移除方块</button>
    <script>
        let square = document.getElementById('animatedSquare');
        const removeButton = document.getElementById('removeButton');
        
        // 存储事件监听器引用,以便后续移除
        const handleRemove = () => {
            if (square) {
                // 1. 使用animation-play-state来暂停动画
                square.classList.add('animation-paused');
                
                // 2. 给一点时间让浏览器应用暂停状态
                requestAnimationFrame(() => {
                    // 3. 移除元素
                    square.remove();
                    
                    // 4. 清除引用
                    square = undefined;
                    console.log("方块已移除");
                    
                    // 5. 移除事件监听器
                    // removeButton.removeEventListener('click', handleRemove);
                });
            }
        };
        removeButton.addEventListener('click', handleRemove);
    </script>
</body>
</html>

当你一直打开Devtools工具时(即按开F12),然后点击移除元素。然后测试一下,发现仍然存在分离元素,如下图:

Snipaste_2025-04-29_23-07-00.png

明明已经移除所有事件、排除了全局变量的原因,还是有内存泄漏的问题。我这边经过chrome134、chrome135验证两个版本的验证,都存在。

没别的了,就是Devtools的问题。按照Chromium项目人员解释的原因,如下图:

image.png

翻译中心思想就是,Animations (动画) 面板中保留了对动画元素的引用。

所以要测试带有动画元素的组件,需要在操作完毕之后,再打开Devtools面板。

Vue的slot的BUG

还是先上链接,有条件的可以看vue的commit。点这里

没条件,我这边可以举例子来解释下。

假如有这么一个父组件:

<template>
    <div>
        <slot></slot>
    </div>
</template>

然后我引用这个组件。

<template>
    <ParentJBK v-if="!model">111</ParentJBK>
    <button @click="fn1">Hidden</button>
</template>

<script>
import { ref } from 'vue'
imprt ParentJBK from './parentJBK.vue'

export default {
    components:{
        ParentJBK
    },
    setup(){
        const model = ref(false)
        
        function fn1(){
            model.value = true;
        }
        
        return {
            model,
            fn1
        }
    }
}

</script>

按照上面的,如果在父组件下,填充了元素。那么,这个时候去销毁掉父组件元素,就会在分离元素下出现销毁的div元素。有意愿的可以动手试试。

看上面的那个commit,大概思路就是在父组件销毁后,顺道把slot销毁掉。

再次崩溃

经过这么一轮,我觉的,给来个痛快的吧。

Snipaste_2025-04-29_23-02-33.png

以上的发现,都是在提了Element-plut的issues后,经过Element-plus贡献者提出的。然后涉及的背后问题,我事先是想都想不到的。谁敢想Devtools都有问题,原来可是我朝圣的对象啊~。。。

调整后的结论

经过上述问题,我重新调整了测试方法,然后根据目前我所知的来测试,在Element-plus组件中,还会存在泄漏的组件如下:

  • el-select
  • el-popper
  • el-carousel
  • el-tabs
  • el-button
  • el-menu
  • el-dropdown
  • el-result
  • el-descriptions

最后说下

对于内存泄漏问题,这里有必要再和大家颗粒度对齐下~

image.png

内存泄漏是指程序在申请使用内存后,无法在程序关闭后正常释放应该释放的内存,导致此内存一直被占据。

用上面这个例子解释就是,当我们使用JS去销毁DOM元素后,但因为某些JS变量或者事件或者哪个回调函数中还存在引用这段DOM元素,导致DOM树上的元素是被移除了,而内存却还保留了DOM元素数据。结果就是随着操作一直增加,占用内存得不到释放,该程序使用的内存就会一直增加。

之前评论中,有些前端大佬说,使用Element-plus组件,总是卡。我们倒可以先分析分析,看看是不是在渲染的时候,出现了跳帧的情况。即元素节点渲染过多或者JS某个程序运算过多,造成在16ms左右不能渲染完整。

跳帧情况会很多,大家在juejin中看看其他大佬的文章,有很多说明。

才疏学浅,随时接受大佬的赐教~

评论也可以贴出自己的问题,大家共同进步respect!