核心隐喻: onMounted 就像房子盖好后的软装进场(挂窗帘)。
一、概念速览
【30秒能读完】
定义:在组件的 DOM 元素 真正挂载到屏幕上之后,立即执行的回调函数。
import { onMounted } from 'vue'
onMounted(() => {
console.log('房子盖好了,可以挂窗帘了')
})
特性:
- DOM 已存在:此时能获取到
document.getElementById。 - 异步执行:在浏览器渲染完第一帧后运行。
- 只跑一次:组件初始化时运行,更新时不运行。
二、逐题详解
小题1:onMounted 是什么意思?
目标:理解单词含义。
// Mount = 挂载
// 指组件从"图纸"变成"屏幕上的像素"
傻瓜口令:"Mount 就是挂,上墙才能画。"
小题2:怎么读?
目标:正确发音。
读音:/ɒn ˈmaʊntɪd/ (昂-茂-替-得)
小题3:必须写吗?
目标:明确必要性。
结论:不必须。 何时写:除此之外,都不用写。
- 需要操作 DOM(画图表、聚焦输入框)。
- 需要初始化第三方库。
小题4:script setup 不就是运行吗?为何还要它?
目标:区分 setup 和 onMounted。
<script setup>
console.log('1. 画图纸 (Setup)')
import { onMounted } from 'vue'
onMounted(() => {
console.log('3. 交房 (Mounted)')
})
</script>
<template>
<div>2. 盖房子 (Rendering...)</div>
</template>
傻瓜口令:"Setup 画图纸,Mounted 搞装修。"
小题5:显示前还是显示后?
目标:明确时序。
结论:显示后。浏览器先把 HTML 画在屏幕上,用户眼睛看到了,然后 Vue 才执行 onMounted。
小题6:能写 document.getElementById 吗?
目标:DOM 操作安全性。
<script setup>
import { onMounted } from 'vue'
// ❌ 错误:这时墙还没砌好
const el1 = document.getElementById('box') // null
onMounted(() => {
// ✅ 正确:墙砌好了
const el2 = document.getElementById('box') // 拿到元素
})
</script>
<template>
<div id="box"></div>
</template>
傻瓜口令:"找元素,用 Mounted,别的地儿是空气。"
小题7:写三个会怎样?
目标:多重调用。
onMounted(() => console.log('我是第 1 个'))
onMounted(() => console.log('我是第 2 个'))
onMounted(() => console.log('我是第 3 个'))
// 结果:按顺序打印 1, 2, 3
傻瓜口令:"写几个跑几个,排队做核酸。"
小题8:能写 async 吗?
目标:异步支持。
onMounted(async () => {
await fetchData()
console.log('数据回来了')
})
// 现象:Vue 不会等你。它继续干别的事,你慢慢跑。
小题9:需要 import 吗?
目标:引入规则。
// ❌ 报错:onMounted is not defined
onMounted(() => {})
// ✅ 正确
import { onMounted } from 'vue'
onMounted(() => {})
傻瓜口令:"要用它,先引它。"
小题10:能套娃(写在里面)吗?
目标:嵌套规则。
// ❌ 禁止:异步套娃
setTimeout(() => {
onMounted(() => {}) // 报错!Vue 找不到爹了。
}, 1000)
// ❌ 禁止:钩子套钩子
onMounted(() => {
onMounted(() => {}) // 没意义,且危险。
})
傻瓜口令:"钩子别套娃,同步直接挂。"
小题11:v-if 切换会跑吗?
目标:条件渲染触发。
<template>
<Child v-if="show" />
</template>
现象:
show = true-> Child 跑onMounted。show = false-> Child 销毁。show = true-> Child 再次跑onMounted。
傻瓜口令:"v-if 就像开关,开了就挂载。"
小题12:反义词是什么?
目标:了解销毁。
单词:onUnmounted (卸载)
场景:拆房子的时候(组件被销毁)。
小题13:SSR (服务器渲染) 会跑吗?
目标:服务端行为。
现象:不跑。 比喻:服务器只打印图纸(HTML字符串),不盖实体房(DOM),所以没法装修。
小题14:能改 ref 吗?
目标:数据修改。
const count = ref(0)
onMounted(() => {
count.value = 1 // 可以改
})
// 后果:浏览器可能重画一次。如果数据关联界面,用户可能看到闪烁。
小题15:写 alert 会怎样?
目标:阻塞行为。
现象:alert 会卡住浏览器的主线程。
后果:虽然数据可能变了,但界面可能还没刷新。不要用 alert 调试生命周期。
小题16:vs window.onload
目标:区分网页加载与组件挂载。
| onMounted | window.onload |
|---|---|
| 你家交房 | 全小区交房 |
| 快 | 慢 (等图片、广告全加载) |
| 只管这个组件 | 管整个网页 |
小题17:vs Vue2 mounted
目标:版本对比。
结论:时机一样。 写法:
- Vue2:
mounted() { ... }(选项) - Vue3:
onMounted(() => { ... })(组合)
小题18:父子组件顺序?
目标:挂载顺序。
graph TD
父Setup --> 子Setup
子Setup --> 子Mounted
子Mounted --> 父Mounted
傻瓜口令:"子先挂,父后挂。" (孩子先站稳,爸爸才放心)
小题19:能放在 if 里吗?
目标:条件注册。
if (Math.random() > 0.5) {
onMounted(() => console.log('运气好才跑')) // ✅ 可以
}
小题20:有参数吗?
目标:参数签名。
结论:无参数。onMounted((params?) => ...) 里的参数是 undefined。
小题21:有返回值吗?
目标:返回值处理。
结论:Vue 忽略 你的返回值。写 return 也没用。
小题22:漏写括号会怎样?
目标:语法检查。
import { onMounted } from 'vue'
// ❌ 没调用函数
onMounted
// 现象:啥也不会发生,控制台不报错,但钩子没注册。
小题23:必须写箭头函数吗?
目标:回调形式。
结论:必须传一个函数。
onMounted(() => {})(推荐,箭头函数)onMounted(function() {})(普通函数,也可以)onMounted(myFunction)(传函数名,也可以)
三、常见坑位
| 坑 | 表现 | 解法 |
|---|---|---|
| Setup 里找 DOM | document.getElementById 返回 null | 移到 onMounted 里写 |
| 异步套钩子 | setTimeout 里写 onMounted 报错无效 | 提出来,放在最外层 |
| 忘删监听器 | 组件销毁后,resize 事件还在跑 | 在 onUnmounted 里 removeEventListener |
四、速查表
| 特性 | 说明 |
|---|---|
| 心智模型 | 房子盖好 -> 软装进场 |
| 核心 API | import { onMounted } from 'vue' |
| 执行时机 | DOM 渲染完成之后 |
| 常见陷阱 | 不要以为它是 window.onload (它比那个快) |
五、脑图回顾
graph LR
A[Script Setup] -->|1. 画图纸| B(Rendering)
B -->|2. 盖房子| C[浏览器显示 DOM]
C -->|3. 软装进场| D[onMounted 执行]
D --> E{你要干嘛?}
E -->|找元素| F[聚焦/画图]
E -->|发请求| G[拿数据]