Vue 中导致 detached 元素产生的常见行为

Vue 中导致 detached 元素产生的常见行为

在 Vue 应用中,detached 元素指的是已经从 DOM 树中移除但仍然被 JavaScript 引用着的 DOM 节点。这些元素会导致内存泄漏,因为它们占用的内存无法被垃圾回收机制回收。以下是 Vue 中常见会导致 detached 元素产生的行为:

1. 未正确清理的全局事件监听器

javascript 复制代码
mounted() {
  window.addEventListener('resize', this.handleResize)
},
beforeDestroy() {
  // 如果忘记移除监听器,相关元素可能保持引用
  // window.removeEventListener('resize', this.handleResize)
}

2. 第三方库未正确销毁

javascript 复制代码
mounted() {
  this.chart = new Chart(this.$refs.canvas, {...})
},
beforeDestroy() {
  // 如果忘记调用销毁方法
  // this.chart.destroy()
}

3. 未清理的定时器

javascript 复制代码
data() {
  return {
    timer: null
  }
},
mounted() {
  this.timer = setInterval(() => {
    // 一些操作
  }, 1000)
},
beforeDestroy() {
  // 如果忘记清除定时器
  // clearInterval(this.timer)
}

4. 未清理的 Vue 自定义事件

javascript 复制代码
mounted() {
  this.$on('custom-event', this.handleEvent)
},
beforeDestroy() {
  // 如果忘记移除事件监听
  // this.$off('custom-event', this.handleEvent)
}

5. 在组件销毁后仍然持有 DOM 引用

javascript 复制代码
data() {
  return {
    elements: []
  }
},
methods: {
  cacheElement() {
    this.elements.push(document.getElementById('some-element'))
  }
}
// 如果 elements 数组不清空,引用的 DOM 元素会保持
// 这时候包含some-element元素的组件被销毁,DOM的引用依然存在

6. 使用 v-if 切换组件时的引用保留

javascript 复制代码
// 父组件
<template>
  <child-component v-if="showChild" ref="child"/>
</template>

// 如果在其他地方保持了对 this.$refs.child 的引用
// 即使child-component组件被销毁,引用仍然存在
mounted() {
  this.detachedElement = this.$refs.child;
}

如何检测

方式一

  1. 使用 Chrome DevTools 的 Memory 工具
  2. 先手动触发垃圾回收
  3. 拍摄堆快照(Heap snapshot)
  4. 搜索 "detached" 来查找分离的 DOM 树

方式二

  1. 使用 Chrome DevTools 的 Memory 工具
  2. 先手动触发垃圾回收
  3. 拍摄分离的元素(Detached elements)

拍摄分离的元素可能导致原本被回收的 elements 没有被回收,所以多次拍摄会产生影响,关闭 DevTools 或刷新页面后引用会释放。拍摄堆快照无此问题。

相关推荐
Jinxiansen02115 分钟前
Vue 3 弹出式计算器组件(源码 + 教程)
前端·javascript·vue.js
东京老树根9 分钟前
SAP学习笔记 - 开发22 - 前端Fiori开发 数据绑定(Jason),Data Types(数据类型)
前端·笔记·学习
前端 贾公子21 分钟前
手写 vue 源码 === runtime-dom 实现
前端·javascript·css
江城开朗的豌豆36 分钟前
JavaScript篇:typeof 的魔法:原来你是这样判断类型的!
前端·javascript·面试
江城开朗的豌豆38 分钟前
JavaScript篇:数组扁平化:从‘千层饼’到‘一马平川’的六种神操作 🥞→📜
前端·javascript·面试
難釋懷3 小时前
Vue-Todo-list 案例
前端·vue.js·list
前端达人3 小时前
React 播客专栏 Vol.18|React 第二阶段复习 · 样式与 Hooks 全面整合
前端·javascript·react.js·前端框架·ecmascript
GISer_Jing3 小时前
Monorepo 详解:现代前端工程的架构革命
前端·javascript·架构
比特森林探险记4 小时前
Go Gin框架深度解析:高性能Web开发实践
前端·golang·gin
打小就很皮...6 小时前
简单实现Ajax基础应用
前端·javascript·ajax