🔍 一、onMounted()
是什么?它的核心作用
onMounted() 是 Vue 3 组合式 API 中的生命周期钩子,用于在组件挂载到 DOM 后执行逻辑。其核心作用包括:
- 访问 DOM 元素:确保 DOM 已渲染完成,可安全操作。
- 初始化副作用:如事件监听、第三方库初始化、数据请求。
- 执行一次性任务:如日志记录、性能监控埋点。
🛠️ 二、基础使用与语法
1️⃣ 基本语法
在组合式 API(<script setup>)中使用:
<script setup>
import { onMounted } from 'vue'
// 定义逻辑
onMounted(() => {
console.log('组件已挂载')
// 访问 DOM 或初始化操作
})
</script>
2️⃣ 对比选项式 API
选项式 API 中的 mounted 钩子:
export default {
mounted() {
console.log('组件已挂载')
}
}
3️⃣ 注册多个钩子
可多次调用 onMounted(),按注册顺序执行:
onMounted(() => {
console.log('第一个挂载钩子')
})
onMounted(() => {
console.log('第二个挂载钩子')
})
// 输出顺序:第一个 → 第二个
🚀 三、核心应用场景
1️⃣ 访问 DOM 元素
结合 ref() 获取模板引用:
<template>
<input ref="inputRef" />
</template>
<script setup>
import { ref, onMounted } from 'vue'
const inputRef = ref(null)
onMounted(() => {
inputRef.value.focus() // DOM 已渲染,安全访问
})
</script>
2️⃣ 初始化第三方库
初始化需要 DOM 的库(如图表、地图):
import { onMounted } from 'vue'
import echarts from 'echarts'
const initChart = () => {
const chart = echarts.init(document.getElementById('chart'))
chart.setOption({ /* ... */ })
}
onMounted(initChart)
3️⃣ 发起异步数据请求
组件挂载后加载数据:
const loadData = async () => {
const res = await fetch('/api/data')
data.value = await res.json()
}
onMounted(() => {
loadData()
})
🚨 四、常见陷阱与解决方案
1️⃣ 异步操作与组件卸载竞态
问题:组件卸载后异步回调仍可能执行,导致内存泄漏或错误。
解决:使用标志变量或清理函数:
let isMounted = true
onMounted(() => {
fetchData().then(res => {
if (isMounted) {
// 处理数据
}
})
})
onUnmounted(() => {
isMounted = false
})
2️⃣ SSR 环境下的 DOM 访问
问题:服务端渲染时,onMounted() 不会执行,直接访问 DOM 会报错。
解决:使用 onMounted() 确保代码仅在客户端运行:
onMounted(() => {
// 仅客户端执行的代码
if (typeof window !== 'undefined') {
initClientOnlyLib()
}
})
3️⃣ 依赖未就绪的子组件
问题:父组件onMounted 触发时,子组件可能尚未挂载。
解决:在子组件中执行逻辑,或使用 nextTick:
onMounted(() => {
nextTick(() => {
// 确保子组件已挂载
})
})
🔧 五、进阶技巧与最佳实践
1️⃣ 与 onUnmounted()
配合清理副作用
onMounted(() => {
const timer = setInterval(() => {
// 轮询任务
}, 1000)
// 组件卸载时清理
onUnmounted(() => {
clearInterval(timer)
})
})
2️⃣ 封装可复用的挂载逻辑
使用组合式函数抽象逻辑:
// useAutoFocus.js
export function useAutoFocus(refName) {
const elementRef = ref(null)
onMounted(() => {
if (elementRef.value) {
elementRef.value.focus()
}
})
return { [refName]: elementRef }
}
// 组件中使用
const { inputRef } = useAutoFocus('inputRef')
3️⃣ 性能优化:避免阻塞主线程
耗时操作放入 requestIdleCallback:
onMounted(() => {
requestIdleCallback(() => {
// 执行非关键任务
})
})
🌟 六、总结:onMounted()
使用要点
场景 | 最佳实践 |
---|---|
DOM 操作 | 结合模板 ref 访问,确保 DOM 已渲染 |
数据请求 | 处理竞态条件,及时清理异步任务 |
第三方库初始化 | 仅在客户端执行(SSR 兼容) |
副作用管理 | 使用 onUnmounted 清理监听器、定时器 |
性能敏感操作 | 拆分任务或使用 Web Worker |
📢 讨论:你在使用 onMounted() 时遇到过哪些问题?如何优化挂载时的性能?欢迎分享经验!👇