Vue.js 3 卸载和内存泄漏

标签 vue.js memory-leaks vuejs3

为了这篇文章的目的,我创建了一个简单的例子:
http://wagoon.demoeshop.net/test-remove-vue.html
在此示例中,您将找到两个按钮。

  • 第一个按钮创建 DIV元素,然后创建一个 Vue 应用程序并将其安装到该 div
  • 第二个按钮将取消应用程序

  • 示例代码
    在我的示例中,您会发现两个按钮
    <button type="button" onclick="myTest.mount()">.mount()</button>
    <button type="button" onclick="myTest.unmount()">.unmount()</button>
    
    包含 Vue.js 3
    <script src="https://unpkg.com/vue@next"></script>
    
    整个 javascript 代码包含在函数 testClass() 中出于调试原因:
    function testClass(){
    
       // vueApp is public just for debugging reasons
       this.vueApp = null;
    
       // creates DIV with id #appDiv and apends it to <body>
       function createDiv(){
          var div = document.createElement('div');
          div.id = "appDiv";
          document.body.append(div);
       }
    
       // creates new Vue app and mounts it to #appDiv
       this.mount = function(){
          createDiv();
          this.vueApp = Vue.createApp({"template":"Vue mounted"});
          this.vueApp.mount('#appDiv');
       }
    
       // unmounts Vue app
       this.unmount = function(){
          // MEMORY LEAK HERE:
          this.vueApp.unmount('#appDiv'); // this line should mark vueApp as collectable for garbage collector,it's not
          this.vueApp = null; // event this line does not help
    
          // SOLUTION: only removing app taget element from DOM is marking object created with Vue.createApp()
          // as collectable by garbage collector.
          // document.querySelector('#appDiv').remove();
       }
    
    }
    
    myTest = new testClass();
    
    如何在谷歌浏览器控制台中查找内存泄漏:
    出于调试原因,创建的应用程序存储在 testClass 中的 this.vueApp 中,以便我们可以轻松找到对象 id。只需按照以下步骤
  • 运行代码
  • 单击第一个按钮(.mount Vue 应用程序)。 “Vue 已安装”文本将出现
  • 打开 chrome 控制台并切换到内存选项卡
  • 拍摄堆快照
  • 单击第二个按钮(.unmount Vue 应用程序)。 “Vue 已安装”文本将消失
  • 返回内存选项卡,点击“收集垃圾”(带有垃圾箱的图标)
  • 拍摄第二个堆快照
  • 切换到第一个快照并过滤“testClass”。 (您只会看到一个结果)。打开它并找到公共(public)属性“vueApp”。在它旁边,您将找到存储在此属性中的对象的@ID(例如@567005)
  • 切换到第二个快照并按 CTRL+F(查找)。搜索相同的@ID(例如@567005)。这是内存泄漏:使用 Vue.createApp 创建的对象仍在内存中!它没有被垃圾收集器收集,因为有些东西仍然指向这个对象

  • 如何解决此内存泄漏
    我找到的唯一解决方案是删除 DIV#appDiv来自 DOM(删除该元素的代码在 myTest.unmount() 方法中注释)。之后,再次调用垃圾收集器将从内存中删除该对象。
    还有其他解决方案吗?
    为什么这是(大)问题
    在具有多个屏幕的大应用程序中,创建和删除整个应用程序是唯一的方法,如何节省内存(脚本只是加载实际页面的代码,当用户想要另一个页面时,实际页面被破坏并加载新页面,然后新的 Vue应用程序已创建)
    你也不能通过创建动态组件来解决这个问题,因为 Vue3 删除了(我认为这是一个很大的错误) $destroy 方法,所以当你为新屏幕创建新组件时,旧组件将永远保留在内存中。
    Vue路由器不会解决这个问题,因为Vue路由器在启动时会加载所有页面,这在大型应用程序中是 Not Acceptable ,因为网络带宽会很大(只为一个应用程序加载兆字节的代码是错误的)

    最佳答案

    在 VUE 3.0.6 中修复
    VUE js 3.0.6 版本修复了这个问题

    关于Vue.js 3 卸载和内存泄漏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65475604/

    相关文章:

    java - 如何找到内存泄漏的根源?

    html - 是否可以有条件地渲染布局?

    javascript - 如何在VUE3中过滤来自代理的记录?

    javascript - 从 vuex 状态数组中创建计算属性数组以在 v-model 中使用

    javascript - 使用 Ctrl+C 终止运行 Vue.js 的 webpack 后,sockjs-node Cross-Origin Request Blocked 警告

    javascript - Vuex - 存储状态对象的类型未知

    javascript - Vue.js AJAX 列表渲染检查是否准备好?

    com - CComBSTR 的内存泄漏

    css - 具有不同背景颜色的相同组件

    android - 为什么应用程序及其资源在退出后仍保留在内存中?