Vue.js 3卸载和内存泄漏

Vue.js 3卸载和内存泄漏,vue.js,memory-leaks,vuejs3,Vue.js,Memory Leaks,Vuejs3,为了写这篇文章,我创建了一个简单的例子: 在本例中,您将发现两个按钮 第一个按钮创建DIV元素,然后创建一个Vue应用程序并将其装载到该DIV 第二个按钮将卸载应用程序 示例代码 在我的示例中,您将发现两个按钮 .mount() .unmount() 包括Vue.js 3 出于调试原因,整个javascript代码被包装在函数testClass()中: 函数testClass(){ //vueApp是公共的,只是出于调试原因 this.vueApp=null; //创建id为appD

为了写这篇文章,我创建了一个简单的例子:

在本例中,您将发现两个按钮

  • 第一个按钮创建
    DIV
    元素,然后创建一个Vue应用程序并将其装载到该
    DIV
  • 第二个按钮将卸载应用程序
示例代码 在我的示例中,您将发现两个按钮

.mount()
.unmount()
包括Vue.js 3


出于调试原因,整个javascript代码被包装在函数
testClass()
中:

函数testClass(){
//vueApp是公共的,只是出于调试原因
this.vueApp=null;
//创建id为appDiv的DIV并将其apends到
函数createDiv(){
var div=document.createElement('div');
div.id=“appDiv”;
文件.正文.附加(div);
}
//创建新的Vue应用程序并将其装载到#appDiv
this.mount=函数(){
createDiv();
this.vueApp=Vue.createApp({“模板”:“Vue已装入”});
这个.vuepp.mount('#appDiv');
}
//卸载Vue应用程序
this.unmount=函数(){
//此处存在内存泄漏:
this.vueApp.unmount(“#appDiv”);//此行应将vueApp标记为垃圾收集器可回收,而不是
this.vueApp=null;//事件此行没有帮助
//解决方案:只有从DOM中删除app taget元素才能标记使用Vue.createApp()创建的对象
//由垃圾收集器收集。
//document.querySelector('#appDiv').remove();
}
}
myTest=新的testClass();
如何在google chrome控制台中查找内存泄漏: 出于调试原因,创建的应用程序存储在testClass中的this.vueApp中,因此我们可以轻松找到对象id。只需遵循以下步骤

  • 运行代码
  • 单击第一个按钮(.mount Vue app)。将显示“Vue已安装”文本
  • 打开chrome控制台并切换到内存选项卡
  • 拍摄堆快照
  • 单击第二个按钮(.unmount Vue app)。“Vue已安装”文本将消失
  • 返回内存选项卡,单击“收集垃圾”(带有垃圾箱的图标)
  • 获取第二个堆快照
  • 切换到第一个快照并过滤“testClass”。(您将只看到一个结果)。打开它并找到公共属性“vueApp”。在它旁边,您将找到存储在此属性中的对象的@ID(例如@567005)
  • 切换到第二个快照并按CTRL+F(查找)。搜索相同的@ID(例如@567005)。内存泄漏:使用Vue.createApp创建的对象仍在内存中!它不是用垃圾收集器收集的,因为仍有东西指向此对象
  • 如何解决这个内存泄漏 我找到的唯一解决方案是从DOM中删除
    DIV#appDiv
    (删除此元素的代码在
    myTest.unmount()方法中注释)。之后,再次调用垃圾收集器将从内存中删除此对象

    还有其他解决方案吗?

    这个(大)问题是什么 在具有多个屏幕的大型应用程序中,创建和删除整个应用程序是唯一的方法,如何节省内存(脚本只加载实际页面的代码,当用户需要另一个页面时,会销毁实际页面并加载新页面,然后创建新的Vue应用程序)

    创建动态组件也不能解决这个问题,因为Vue3删除了$destroy方法(我认为这是一个很大的错误),所以当您为新屏幕创建新组件时,旧组件将永远保留在内存中


    Vue router无法解决此问题,因为Vue router在启动时加载所有页面,这在大型应用程序中是不可接受的,因为网络带宽将非常大(仅为一个应用程序加载兆字节的代码是错误的)

    在Vue 3.0.6中已修复
    VUE js 3.0.6版修复了此问题

    “VUE路由器在开始时加载所有页面”-路由器正在使用import(),这可以通过“延迟加载”方式(按需加载)完成。但这不是问题所在。问题是:如果您使用路由器,您无法从内存中删除(或“卸载”)导入模块。但这篇文章不是关于路由器的,而是关于unmount()方法的,值得在vue3 github中创建问题:谢谢,我创建了新的报告,所以听起来我们不需要卸载vue应用程序就可以对其进行垃圾收集?那么简单地删除dom根元素就足以将其标记为垃圾收集?还是我误解了。我将删除许多包含已装入的vue应用程序实例的dom元素,然后重新装入新的实例,因此了解这对内存的影响将是非常好的。如果您进一步了解它现在是如何修复的,或者提供一个链接,因为OP写了一个非常详细的解释,这个解释可以被认为是以多种方式“固定”的