Vue3 生命周期梳理与实战注意点
生命周期这道题看着基础,但面试官常会追问「和 Vue2 差在哪」「
setup里为什么少用onMounted之前的同步请求」之类。下面按 Options API 和 Composition API 各记一版,并写两个项目里常见的坑。
题目
Vue3 的生命周期有哪些?分别在什么时机执行?
先对齐:两套写法
Vue3 仍然支持 Vue2 的 Options API(beforeCreate、created…),同时推荐 Composition API 里以 onXxx 钩子函数注册。面试时两套都能说,最好补一句:<script setup> 里没有 beforeCreate / created,它们的逻辑合并进 setup 执行阶段。
| 阶段(通俗) | Options API | Composition API (<script setup>) |
|---|---|---|
| 创建前后 | beforeCreate、created | 由 setup() 本身替代 |
| 挂载前后 | beforeMount、mounted | onBeforeMount、onMounted |
| 更新前后 | beforeUpdate、updated | onBeforeUpdate、onUpdated |
| 卸载前后 | beforeUnmount、unmounted | onBeforeUnmount、onUnmounted |
| 错误捕获 | errorCaptured | onErrorCaptured |
| 仅 keep-alive | activated、deactivated | onActivated、onDeactivated |
Vue3 改名对照:beforeDestroy → beforeUnmount,destroyed → unmounted。
执行顺序(挂载一条线)
父、子同时存在时,创建阶段父先子后,挂载阶段子先父后(经典八股,画个图更好记):
父 beforeCreate → 父 created → 子 beforeCreate → 子 created
→ 父 beforeMount → 子 beforeMount → 子 mounted → 父 mountedComposition API 里只要在 setup 同步注册 onMounted 等,Vue 会按组件树规则排队执行。
实践示例:请求放哪、清理放哪
1. 拉列表数据 — 放 onMounted
DOM 还没好时去操作节点容易报错;首屏请求一般等挂载后(或 setup 里直接 await 配合 Suspense,看项目架构)。
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import { fetchList } from '@/api/order'
const list = ref([])
let timer = null
onMounted(async () => {
list.value = await fetchList()
// 轮询别忘清理
timer = setInterval(() => refresh(), 5000)
})
onUnmounted(() => {
if (timer) clearInterval(timer)
})
</script>2. 监听窗口尺寸 — 注册在 mounted,卸载必须拆
<script setup>
import { onMounted, onUnmounted } from 'vue'
function onResize() {
console.log(window.innerWidth)
}
onMounted(() => window.addEventListener('resize', onResize))
onUnmounted(() => window.removeEventListener('resize', onResize))
</script>3. onUpdated 慎用
每次依赖变更导致重渲染都会走,在这里改 state 容易死循环。我更多用 watch / watchEffect 代替「数据变了再干一件事」。
<script setup>
import { ref, watch } from 'vue'
const count = ref(0)
// 比 onUpdated 更清晰
watch(count, (n) => {
document.title = `点击 ${n} 次`
})
</script>4. keep-alive 缓存页
列表进详情再返回,想保留滚动位置,会用 onActivated / onDeactivated:
<script setup>
import { onActivated, onDeactivated } from 'vue'
onActivated(() => {
// 从缓存恢复,可刷新数据或恢复滚动
})
onDeactivated(() => {
// 页被缓存,不是真卸载
})
</script>和 Vue2 面试常问的对比点
setup在beforeCreate之前执行,此时实例还没完全建好,所以 没有this- 想访问
props、emit,在setup参数或defineProps/defineEmits里拿- 异步
setup(<script setup>+ 顶层await)会配合<Suspense>,和生命周期钩子并行概念要分开
答题小结(口述版)
按创建 → 挂载 → 更新 → 卸载四条线说钩子名;补充 <script setup> 用 onMounted 等函数注册;强调 onUnmounted 里清定时器、解绑事件、取消请求(若用了 AbortController)。有 keep-alive 再提 activated / deactivated。
写在最后
生命周期题不容易挂,挂的多半是「忘了卸载」导致内存泄漏。面试前我会扫一眼项目里有没有 addEventListener、setInterval、第三方图表实例,对应钩子是否成对。
创作不易,转载请注明出处和作者。
