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。合理運用這些鈎子,能讓我們在組件的不同階段精準控制邏輯,確保代碼執行的時機正確,提升應用的穩定性和性能。