Vue生命周期 鈎子函數
每個 Vue 實例在被創建時都要經過一系列的初始化過程——例如,需要設置數據監聽、編譯模板、將實例掛載到 DOM 並在數據變化時更新 DOM 等。
同時在這個過程中也會運行一些叫做生命周期鈎子的函數,這給了用戶在不同階段添加自己的代碼的機會。(來源:官方文檔)
官方生命周期圖示:
生命周期的鈎子函數見下表
鈎子函數 | 觸發的行為 | 在此階段可以做的事情 |
beforeCreadted | vue實例的掛載元素$el和數據對象data 都為undefined,還未初始化。 |
加loading事件 |
created | vue實例的數據對象data有了,$el還沒有 |
結束loading、請求數據為mounted渲染做准備 |
beforeMount | vue實例的$el和data都初始化了,但還是虛擬的dom節點, 具體的data.filter還未替換。 |
... |
mounted | vue實例掛載完成,data.filter成功渲染 | 配合路由鈎子使用 |
beforeUpdate | data更新時觸發 | ... |
updated | data更新時觸發 | 數據更新時,做一些處理(此處也可以用 watch進行觀測) |
beforeDestroy | 組件銷毀時觸發 | ... |
destroyed | 組件銷毀時觸發,vue實例解除了事件監聽以及和dom的綁定 (無響應了),但DOM節點依舊存在 |
組件銷毀時進行提示 |
說明一下:
beforeCreate:el 和 data 並未初始化 (此方法不常用)
created:完成了 data 數據的初始化,el的初始化未完成。用來發送ajax
beforeMount:(執行此方法時已經完成了 el 和 data 初始化 (已經賦予了對應的值))
渲染DOM之前先確認下是否有要編譯的根元素(有無el屬性),有才繼續確認是否具有模板屬性template
,如果有模版屬性,則會用template
的值替
換掉HTML中的結構,template
模版中只能有一個根元素(而且不能是文本);
mounted:(執行此方法時代表已經掛載結束了)
把編譯好的數據掛載到DOM元素上,最后渲染成真實的DOM元素;真實DOM已經渲染完成,可以操作DOM了
beforeUpdate:當頁面依賴的數據更改之后觸發(此時DOM結構還沒有重新加載)
updated:DOM結構重新加載之后觸發
調用vm.$destroy()之后觸發下面兩個事件:
beforeDestroy:實例銷毀之前調用。在這一步,實例仍然完全可用。(可在此處清除定時器,清除事件綁定)
destroyed:Vue 實例銷毀后調用。調用后,Vue 實例指示的所有東西都會解綁定,所有的事件監聽器會被移除,所有的子實例也會被銷毀。
destroyed鈎子函數有一點一定要特別注意:在執行destroy方法后,對data的改變不會再觸發周期函數,此時的vue實例已經解除了事件監聽
以及和dom的綁定,但是dom結構依然存在。所以對於實時顯示的通知型組件,在他destroyed之前,我們必須手動removeChild()刪除該節點;
否則,DOM節點還是存在,影響瀏覽器性能。
注意:
所有的生命周期鈎子自動綁定this上下文到實例中,因此你可以訪問數據,對屬性和方法進行運算。這意味着你不能使用箭頭函數來定義一個
生命周期方法(例如created: () => this.fetchTodos())。這是因為箭頭函數綁定了父上下文,因此this與你期待的 Vue 實例不同,
this.fetchTodos的行為未定義。
測試代碼:
export default { data () { return { todos: [], allCounts: 0, filter: 'all', id: 0, states: ['all', 'active', 'completed'] } }, beforeCreate () { console.log('==============' + 'beforeCreated' + '===================') console.log(this.$el) console.log(this.$data) console.log(this.filter) }, created () { console.log('==============' + 'created' + '===================') console.log(this.$el) console.log(this.$data) console.log(this.filter) }, beforeMount () { console.log('==============' + 'beforeMount' + '===================') console.log(this.$el) console.log(this.$data) console.log(this.filter) }, mounted () { console.log('==============' + 'mounted' + '===================') console.log(this.$el) console.log(this.$data) console.log(this.filter) }, beforeUpdate () { console.log('==============' + 'beforeUpdate' + '===================') console.log(this.$el) console.log(this.$data) console.log(this.filter) }, updated () { console.log('==============' + 'updated' + '===================') console.log(this.$el) console.log(this.$data) console.log(this.filter) }, beforeDestroy () { console.log('==============' + 'beforeDestroy' + '===================') console.log(this.$el) console.log(this.$data) console.log(this.filter) }, destroyed () { console.log('==============' + 'destroyed' + '===================') console.log(this.$el) console.log(this.$data) console.log(this.filter) } }
測試結果:
組件傳值
Vue常用的三種傳值方式有:
父傳子
子傳父
非父子傳值
引用官網的一句話:父子組件的關系可以總結為 prop 向下傳遞,事件向上傳遞。父組件通過 prop 給子組件下發數據,子組件通過事件給父
組件發送消息。
1.父組件向子組件進行傳值
父組件
<template>
<div> 父組件: <input type="text" v-model="name">
<br>
<br>
<!-- 引入子組件 -->
<child :inputName="name"></child>
</div>
</template>
<script> import child from './child' export default { components: { child }, data () { return { name: '' } } } </script>
子組件
<template>
<div> 子組件: <span>{{inputName}}</span>
</div>
</template>
<script> export default { // 接受父組件的值
props: { inputName: String, required: true } } </script>
子組件通過props接收父組件傳回的值
2.子組件向父組件傳值
父組件
<template>
<div> 父組件: <span>{{name}}</span>
<br>
<br>
<!-- 引入子組件 定義一個on的方法監聽子組件的狀態-->
<child v-on:childByValue="childByValue"></child>
</div>
</template>
<script> import child from './child' export default { components: { child }, data () { return { name: '' } }, methods: { childByValue: function (childValue) { // childValue就是子組件傳過來的值
this.name = childValue } } } </script>
子組件
<template>
<div> 子組件: <span>{{childValue}}</span>
<!-- 定義一個子組件傳值的方法 -->
<input type="button" value="點擊觸發" @click="childClick">
</div>
</template>
<script> export default { data () { return { childValue: '我是子組件的數據' } }, methods: { childClick () { // childByValue是在父組件on監聽的方法
// 第二個參數this.childValue是需要傳的值
this.$emit('childByValue', this.childValue) } } } </script>
子組件通過事件派發向父組件傳值
3.兄弟組件通信
通過事件總線的方式實現就是一個空的vue示例只用來綁定方法。
舉個例子:
1 在main.js中全局注冊一個
data:{ eventHub: new Vue() }
2 在組件a里定義需要傳的參數
self.$root.eventHub.$emit('add',{tabnum:tab.index,yuid:tab.$vnode.key,);
3 在組件b里取得需要接受的參數
self.$root.eventHub.$on('add',function(data) { self.tabnum = data.tabnum; self.yunid = data.yuid; } })