Vue 3 中,unmounted 生命周期钩子会在组件实例被销毁并从 DOM 中移除后调用

Vue3中unmounted钩子在组件销毁时触发,常见场景包括:

  1. v-if条件变化;
  2. 动态组件切换;
  3. 路由导航;
  4. v-for列表更新;
  5. 父组件卸载;
  6. 手动调用unmount();
  7. Teleport目标移除;
  8. 组合式API停止响应式效果。

KeepAlive缓存的组件会触发deactivated而非unmounted。


最佳实践是在unmounted中清理定时器、事件监听等资源,避免内存泄漏。


理解这些触发条件有助于更好地管理组件生命周期。


在 Vue 3 中,unmounted 生命周期钩子会在组件实例被销毁并从 DOM 中移除后调用。


以下是会触发组件卸载(unmount)的常见情景:


1. 条件渲染导致的组件移除

vue

复制代码
<template>
  <ChildComponent v-if="showChild" />
</template>

<script setup>
import { ref } from 'vue'
const showChild = ref(true)

// 当 showChild 变为 false 时,ChildComponent 会被卸载
setTimeout(() => {
  showChild.value = false  // 触发 ChildComponent 的 unmount
}, 3000)
</script>

2. 动态组件切换

vue

复制代码
<template>
  <component :is="currentComponent" />
</template>

<script setup>
import { ref, shallowRef } from 'vue'
import ComponentA from './ComponentA.vue'
import ComponentB from './ComponentB.vue'

const currentComponent = shallowRef(ComponentA)

// 切换组件时,前一个组件会被卸载
const switchComponent = () => {
  currentComponent.value = ComponentB  // ComponentA 会被卸载
}
</script>

3. 路由导航

javascript

复制代码
// 路由导航时,离开当前路由对应的组件会被卸载
router.push('/new-route')  // 当前路由组件会被卸载(如果不需要被缓存)

4. v-for 列表项变化

vue

复制代码
<template>
  <div v-for="item in list" :key="item.id">
    <ListItem :item="item" />
  </div>
</template>

<script setup>
import { ref } from 'vue'

const list = ref([
  { id: 1, name: 'Item 1' },
  { id: 2, name: 'Item 2' }
])

// 移除数组元素时,对应的组件会被卸载
const removeItem = (id) => {
  list.value = list.value.filter(item => item.id !== id)
}
</script>

5. 父组件被卸载

vue

复制代码
<template>
  <ParentComponent v-if="showParent">
    <!-- 当 ParentComponent 被卸载时,所有子组件也会被卸载 -->
    <ChildComponent />
  </ParentComponent>
</template>

6. 手动卸载组件

vue

复制代码
<template>
  <div ref="container"></div>
</template>

<script setup>
import { ref, onMounted, createApp } from 'vue'
import DynamicComponent from './DynamicComponent.vue'

const container = ref(null)
let appInstance = null

onMounted(() => {
  // 手动挂载组件
  appInstance = createApp(DynamicComponent)
  appInstance.mount(container.value)
  
  // 手动卸载组件
  setTimeout(() => {
    appInstance.unmount()  // 触发 unmount
    container.value.innerHTML = ''
  }, 5000)
})
</script>

7. 使用 <Teleport> 但目标元素被移除

vue

复制代码
<template>
  <Teleport :to="target">
    <Modal />
  </Teleport>
</template>

<script setup>
import { ref } from 'vue'

const target = ref('body')

// 如果目标元素被从 DOM 中移除,通过 Teleport 传送的组件也会被卸载
</script>

8. 在组合式 API 中手动停止响应式效果

vue

复制代码
<script setup>
import { onUnmounted } from 'vue'

// 当组件被卸载时,onUnmounted 钩子会被调用
onUnmounted(() => {
  console.log('组件已卸载')
  // 清理工作,如清除定时器、取消事件监听等
})
</script>

特殊情况:组件不会被卸载

使用 <KeepAlive> 缓存组件

vue

复制代码
<template>
  <KeepAlive>
    <ComponentA v-if="showA" />
    <ComponentB v-else />
  </KeepAlive>
</template>
  • 组件切换时不会触发 unmounted,而是触发 deactivated

  • 从缓存中移除时才会触发 unmounted


使用 <Suspense> 的异步组件

异步组件的加载和卸载有特殊处理,但最终卸载时仍会触发 unmounted


最佳实践

unmountedonUnmounted 中:

  1. 清理定时器

  2. 取消事件监听器

  3. 清理第三方库实例

  4. 取消网络请求

  5. 清理全局状态监听


vue

复制代码
<script setup>
import { onUnmounted } from 'vue'

let intervalId

onMounted(() => {
  intervalId = setInterval(() => {
    console.log('定时执行')
  }, 1000)
})

onUnmounted(() => {
  clearInterval(intervalId)  // 清理定时器
})
</script>

理解这些触发情景有助于更好地管理组件生命周期和资源清理。

相关推荐
A黄俊辉A1 天前
uniapp webview中实现 app和内嵌的H5双向通信
vue.js·json
honkun61 天前
vue 表格组件 vxe-table 配置 ajax 请求自动加载数据与表单查询
vue.js·vxe-table
kybs19911 天前
全球灾害数据分析可视化 毕业设计-附源码66794
vue.js·spring boot·mysql·安全·django·c#·asp.net
雪芽蓝域zzs1 天前
第26章:ECharts 自定义主题 + 页面一键切换主题(深色 / 浅色两套)
vue.js·echars
雪芽蓝域zzs1 天前
第22章:ECharts 图表联动(多图表交互联动)
vue.js·echars
daols881 天前
vue 表格组件 vxe-table 实现虚拟滚动与无需滚动加载
vue.js·vxe-table
雪芽蓝域zzs1 天前
第18章:ECharts 折线图 + 标记点、标记线,自定义 tooltip
vue.js·echars
雪芽蓝域zzs1 天前
第24章:ECharts 地图组件(基础行政区地图,若依 Vue3)
vue.js·echars
计算机毕设定制辅导-无忧学长1 天前
《基于Vue的流浪动物救助中心管理系统的设计与实现》
java·vue.js·spring boot·流浪动物救助中心管理系统
雪芽蓝域zzs1 天前
第25章:地图下钻交互(点击省份,切换到对应省份城市地图)
vue.js·echars