??????? 當我們運行vue項目,看到了屏幕上顯示的界面,看到了界面上顯示的數據和標簽,之后將這個界面叉掉,這一過程其實經歷了一整個vue的生命周期的四個階段,即創建階段、掛載階段、更新階段以及銷毀階段, 而對于每個階段的啟動前和完成后,都可以使用一對鉤子來訪問。
一、創建階段 (beforeCreate/created兩鉤子)
- beforeCreate:在實例初始化之后,數據觀測 和 事件/偵聽器的配置之前被調用。此時,組件的
data
、computed
、watch
、methods
上的方法和數據都不可訪問,例如我提前在data中定義了一個變量,在該階段訪問它,只會獲得空值。 - created:在實例創建完成后被立即調用。在這一步,實例已完成以下的配置:數據觀測,屬性和方法的運算,
watch/event
事件回調。然而,掛載階段還沒開始,$el
屬性目前不可見。
<template> <div>{{ message }}</div>
</template> <script>
export default { data() { return { message: 'Hello Vue!' } }, beforeCreate() { console.log('beforeCreate:', this.message); // undefined,因為data還未初始化 // 這里可以初始化一些不需要依賴data或methods的屬性 }, created() { console.log('created:', this.message); // Hello Vue!,此時data已初始化 // 這里可以調用API,獲取數據等 this.fetchData(); }, methods: { fetchData() { // 模擬異步獲取數據 setTimeout(() => { // 假設這里是從服務器獲取的數據 const newData = 'New message from server'; // 注意:直接修改data屬性會觸發視圖更新 this.message = newData; }, 1000); } }
}
</script>
二、掛載階段 (beforeMount/mounted)
- beforeMount:在掛載開始之前被調用:相關的 render 函數首次被調用。該鉤子在服務器端渲染期間不被調用。
- mounted:
el
被新創建的vm.$el
替換,并掛載到實例上去之后調用該鉤子。如果根實例掛載了一個文檔內元素,當mounted
被調用時vm.$el
也在文檔內。
<template> <div ref="myDiv">{{ message }}</div>
</template> <script>
export default { data() { return { message: '存儲的內容' } }, beforeMount() { // 這里的$el存在,但內容還是模板字符串 console.log('beforeMount:', this.$el.textContent); // 可能是空字符串或注釋 }, mounted() { // 組件已掛載到DOM上,可以訪問到DOM元素 console.log('mounted:', this.$refs.myDiv.textContent); // Hello Vue in DOM! // 可以在這里操作DOM,如添加事件監聽器等 this.$refs.myDiv.addEventListener('click', this.handleClick); }, methods: { handleClick() { console.log('myDiv被點擊了'); } }, beforeDestroy() { // 清理事件監聽器,避免內存泄漏 this.$refs.myDiv.removeEventListener('click', this.handleClick); }
}
</script>
三、更新階段(beforeUpdate/updated)
- beforeUpdate:數據更新時調用,發生在虛擬 DOM 打補丁之前。這里適合在更新之前訪問現有的 DOM,比如手動移除已添加的事件監聽器。
- updated:由于數據更改導致的虛擬 DOM 重新渲染和打補丁,在這之后會調用這個鉤子。當這個鉤子被調用時,組件 DOM 已經更新,所以現在可以執行依賴于 DOM 的操作。然而在大多數情況下,應該避免在此期間更改狀態,因為這可能會導致更新無限循環。(我要更新了,但是更新時發現有個東西要更新,之后更新這個東西,但是又發現這個東西要更新,然后又又更新......無限循環)
<template> <div>{{ counter }}</div> <button @click="increment">Increment</button>
</template> <script>
export default { data() { return { counter: 0 } }, beforeUpdate() { console.log('beforeUpdate:', this.counter); // 更新前的值 //此時DOM還未更新 }, updated() { console.log('updated:', this.counter); // 更新后的值 // 可以在這里執行依賴于DOM的操作,但要避免引起無限更新循環 }, methods: { increment() { this.counter++; } }
}
</script>
四、銷毀階段(beforeDestroy/destroyed)
?在這個階段,Vue 實例將從 DOM 中卸載,并且清理所有的綁定和事件監聽。
-
beforeDestroy(): 在實例銷毀之前調用。這時實例仍然完全可用。
-
destroyed(): 在實例銷毀后調用。調用之后,Vue 實例上的所有東西都會解除綁定,所有的事件監聽器會被移除,所有的子實例也會被銷毀。
銷毀階段的代碼我已經融入到前三個階段的代碼中,在此不再展示.
整個流程:
beforeCreate -> created -> beforeMount -> mounted -> beforeUpdate -> updated -> beforeDestroy -> destroyed