Vue 中生命週期鈎子的使用
在 Vue 組件從創建到銷燬的整個過程中,會經歷一系列特定的階段,就像人從出生到成長再到衰老的過程。生命週期鈎子就是在這些階段中自動觸發的函數,讓我們能在合適的時機執行特定操作,比如初始化數據、發送請求、操作 DOM 等,是掌控組件行為的重要工具。
最常用的生命週期鈎子之一是onMounted,它會在組件掛載到 DOM 後立即執行。這時候組件的 DOM 已經渲染完成,非常適合執行需要操作 DOM 的邏輯,或者發送初始化數據的請求:
<template>
<div class="user-profile">
<h3>用户資料</h3>
<p v-if="loading">加載中...</p>
<div v-else>
<p>姓名:{{ user.name }}</p>
<p>年齡:{{ user.age }}</p>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
const user = ref({})
const loading = ref(true)
// 組件掛載後執行
onMounted(() => {
console.log('組件已掛載到DOM')
// 模擬發送請求獲取用户數據
setTimeout(() => {
user.value = { name: '張三', age: 25 }
loading.value = false
// 操作DOM:給標題添加樣式
document.querySelector('h3').style.color = '#2c3e50'
}, 1000)
})
</script>
這裏onMounted中的代碼會在組件成功渲染到頁面後運行,確保我們能安全地訪問和操作 DOM 元素,同時適合在這裏發起數據請求,避免在組件未準備好時執行無效操作。
與onMounted對應的是onUnmounted,它會在組件從 DOM 中卸載(銷燬)時觸發,常用於清理工作,比如清除定時器、取消事件監聽等,避免內存泄漏:
<template>
<div class="timer-demo">
<p>當前時間:{{ currentTime }}</p>
<button @click="isShow = false">銷燬組件</button>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
const currentTime = ref('')
let timer = null
// 組件掛載時創建定時器
onMounted(() => {
timer = setInterval(() => {
currentTime.value = new Date().toLocaleTimeString()
}, 1000)
})
// 組件卸載時清理定時器
onUnmounted(() => {
console.log('組件即將銷燬')
clearInterval(timer)
timer = null // 釋放引用
})
</script>
當組件被銷燬時,onUnmounted會觸發並清除定時器,防止組件已經不存在但定時器仍在運行的情況,這是保持應用性能的重要習慣。
在數據更新導致 DOM 重新渲染後,onUpdated鈎子會被調用,適合在 DOM 更新完成後執行依賴於新 DOM 狀態的操作。比如在列表數據變化後,自動滾動到列表底部:
<template>
<div class="message-list">
<ul ref="listRef">
<li v-for="(msg, index) in messages" :key="index">
{{ msg }}
</li>
</ul>
<button @click="addMessage">添加消息</button>
</div>
</template>
<script setup>
import { ref, onUpdated } from 'vue'
const messages = ref(['第一條消息', '第二條消息'])
const listRef = ref(null)
// 添加新消息
const addMessage = () => {
messages.value.push(`新消息 ${messages.value.length + 1}`)
}
// DOM更新後執行
onUpdated(() => {
console.log('DOM已更新')
// 滾動到列表底部
const list = listRef.value
list.scrollTop = list.scrollHeight
})
</script>
每次點擊 “添加消息” 按鈕,messages數組更新會觸發 DOM 重新渲染,渲染完成後onUpdated會自動執行,將列表滾動到底部,確保用户能看到最新消息。
還有onBeforeMount和onBeforeUnmount這兩個鈎子,分別在組件掛載前和卸載前觸發。onBeforeMount時組件的模板已經編譯完成,但還沒掛載到 DOM,適合做一些掛載前的準備工作;onBeforeUnmount時組件還未被銷燬,仍能訪問組件實例和 DOM,適合做最後的狀態記錄:
<template>
<div class="lifecycle-demo">
<p>生命週期演示</p>
</div>
</template>
<script setup>
import { onBeforeMount, onMounted, onBeforeUnmount, onUnmounted } from 'vue'
onBeforeMount(() => {
console.log('組件即將掛載(DOM未生成)')
})
onMounted(() => {
console.log('組件已掛載(DOM可用)')
})
onBeforeUnmount(() => {
console.log('組件即將卸載(仍可訪問DOM)')
})
onUnmounted(() => {
console.log('組件已卸載(DOM已移除)')
})
</script>
這四個鈎子按順序觸發,完整覆蓋了組件從創建到銷燬的主要階段,打印的日誌能清晰看到組件生命週期的流轉過程。
在使用生命週期鈎子時,需要注意它們的執行時機和適用場景:初始化數據請求、DOM 操作適合在onMounted中進行;清理資源必須放在onUnmounted;依賴 DOM 更新的操作要用到onUpdated。合理運用這些鈎子,能讓我們在組件的不同階段精準控制邏輯,確保代碼執行的時機正確,提升應用的穩定性和性能。