gpt4 book ai didi

vue.js - $emit 导致内存泄漏 - Vue.js

转载 作者:搜寻专家 更新时间:2023-10-30 22:13:13 24 4
gpt4 key购买 nike

我有两个组件。 parent 和 child 。父级根据 v-if 加载子级。然后 child 通过$emit发送一个事件告诉 parent 移除 child 。

简单地说。

家长:

data() {
return {
show: false
}
},
// template:
<div>
<div @click="show = !show">Toggle</div>
<child-component
v-if="show"
@close="show = false"
/>
</div>

child :

template: 
<div>
Some Content
<div @click="$emit('close')">Close</div>
</div>

问题是当 $emit('close') 被触发时,子组件从 DOM 中移除但组件没有从内存中清除。

如果 parent 使用 toggle 按钮移除 child ,它确实会从内存中清除 child 。

我也尝试过使用 Vuex store$root.data 但这也会导致内存泄漏。

换句话说,如果子进程向父进程发出信号,表明它应该被移除,它就会保留在内存中。但是,如果 parent 直接删除 child (没有来自 child 的任何信号),它就会从内存中删除......

知道为什么会发生这种情况以及我应该如何防止这种内存泄漏? child 必须发出要移除的信号。

[编辑] - 代码笔中的演示。 https://codepen.io/tomshort5/pen/BaBLXvb

内存快照

通过在某些操作后制作内存快照,可以最好地看到这一点。当页面加载时,我们有一个 Vue 实例。 On page load

点击toggle后,一个VueComponent就按预期创建了。 After clicking "toggle"

通过事件触发child移除后,VueComponent并没有从内存中移除。将它与再次单击“切换”进行比较时,它确实显示了从内存中删除的组件。 After clicking "Close me"

最佳答案

我有一个部分的解释。

似乎有什么东西保留了对被单击的最后一个 DOM 节点的引用。所以如果你点击 Close它将获取对该文本节点的引用。文本节点的父节点是 <div><div>有一个指向 Vue 组件的点击监听器。组件本身已被销毁,无法进行 GC。

如果您改为单击 Toggle它保留对 Toggle 的引用文本节点。由于该节点位于 DOM 树的不同部分,因此它不会使用点击监听器保留对该元素的任何引用。 Vue组件成功GCed。

我无法准确确定是什么保留了对上次单击节点的引用。堆快照不是特别有用。它只显示 InternalNode正在连接 window到相关的文本节点。

我确实在没有 Vue 的情况下整理了一个页面来探索这个。我的实验表明,即使 Vue 不在页面上,也会保留对最后单击的节点的引用。

这里的内存泄漏只是非常暂时的。在页面上的任意位置再单击一次似乎足以修复它。与我的理论一致,这更新了“最后单击的节点”引用,允许分离的 DOM 节点和 Vue 组件一起被 GC。

关于vue.js - $emit 导致内存泄漏 - Vue.js,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57578842/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com