vue2中@hook的解析與妙用實例
前言
@hook是什么?用來監(jiān)聽組件生命周期的回調(diào)函數(shù)。
這和生命周期函數(shù)mounted,created,updated有什么區(qū)別?
區(qū)別1:@hook 會在對應(yīng)的生命周期函數(shù)執(zhí)行后執(zhí)行。
區(qū)別2:@hook 可以在父組件監(jiān)聽子組件的生命周期運行情況。

從這段vue源代碼中我們能看到hook的部分調(diào)用邏輯,vm.$emit('hook:' + hook) 其實就是在調(diào)用我們寫的@hook:mounted="xxx",@hook這個api卻沒有在官方文檔中出現(xiàn),所以鮮有人知道它的存在和用法。
幾種用法
用法一 將放在多個生命周期的邏輯,統(tǒng)一到一個生命周期中
通常寫法
export default {
components: {},
data: () => {
return {
name: 'dx',
};
},
created() {
console.log('created')
},
beforeMount() {
console.log('beforeMount')
},
mounted() {
console.log(this.name);
// 每一個小時刷新一次頁面
setInterval(() => {
location.reload()
}, 60 * 60 * 1000);
},
}
@hook的用法
export default {
components: {},
data: () => {
return {
name: 'dx',
};
},
created() {
console.log('created');
this.$on('hook:beforeMount', () => {
console.log('beforeMount');
});
this.$on('hook:mounted', () => {
console.log(this.name); // this 就是組件實例自己
// 每一個小時刷新一次頁面
setInterval(() => {
location.reload();
}, 60 * 60 * 1000);
});
},
};
注意
- 按照生命周期執(zhí)行的先后周期,我們只能mounted生命周期里,寫這之后的生命周期,而不能寫
hook:beforeMount this.$on第二個回調(diào)函數(shù)的this指的是當(dāng)前組件實例本身,無論這個回調(diào)函數(shù)是否是箭頭函數(shù)。
用法二 監(jiān)聽子組件生命周期運行的情況
通常寫法
// 父組件
<Children @buttonRender="ButtonRender"/>
export default {
name: 'Parents',
components: {
Children
},
data: () => {
return {
name: 'dx',
};
},
methods: {
ButtonRender() {
console.log('渲染完成')
}
}
}
// 子組件
export default {
name: 'Children',
components: {},
data: () => {},
methods: {},
mounted() {
this.$emit('buttonRender')
}
}
@hook的寫法
<Children @hook:mounted="ButtonRender"/>
export default {
name: 'Parents',
components: {
Children
},
data: () => {
return {
name: 'dx',
};
},
methods: {
ButtonRender() {
console.log('渲染完成')
}
}
}
注意
- @hook的寫法可以不需要在子組件里面編寫其它代碼
- 從vue源碼中可以發(fā)現(xiàn) vm.$emit('hook:' + hook) 這里雖然調(diào)用了hook但沒有返回參數(shù),也就是說,上面代碼中ButtonRender沒有默認(rèn)參數(shù)。
- 同樣承接著2來說,由于ButtonRender沒有默認(rèn)參數(shù),所以我們無法在ButtonRender函數(shù)中獲取子組件Children的實例。
為了解決3的問題,我嘗試著想到一種方法,利用ref獲取子組件的實例,將子組件的實例拿到父組件的this中。ButtonRender中的this就是父組件實例,和尋常methods中的函數(shù)沒區(qū)別。
<Children ref="child1" @hook:mounted="ButtonRender"/>
export default {
name: 'Parents',
components: {
Children
},
data: () => {
return {
name: 'dx'
};
},
mounted() {},
methods: {
ButtonRender() {
console.log(this.$refs.child1) // this.$refs.child1就是子組件Children的實例了
console.log('渲染完成')
}
}
};
但是,我們都知道,vue ref的綁定都是掛載完成之后,所以這個方法也只能用在@hook:mounted 、@hook:updated等mounted之后執(zhí)行的生命周期中,而不能用在 比如@hook:beforeMount中。
運用場景
場景一
許多時候,我們不得不在不同的生命周期中執(zhí)行某些邏輯,并且這些邏輯會用到一些通用的變量,這些通用變量按照之前的方式,我們不得不存在data中。
<script>
export default {
data() {
return {
timer:null
}
}
mounted () {
this.timer = setInterval(() => {
// todo
}, 1000);
}
beforeDestroy () {
clearInterval(this.timer)
}
}
</script>
優(yōu)化后,就不存在這個問題,是不是很好用。
<script>
export default {
mounted () {
const timer = setInterval(() => {
// todo
}, 1000);
this.$once('hook:beforeDestroy', function () {
clearInterval(timer)
})
}
}
</script>
場景二
如果屬于同一業(yè)務(wù)的邏輯要在不同的生命周期中執(zhí)行,下面這樣會更利于閱讀和維護(hù)。
export default {
created() {
this.$on('hook:mounted', () => {
掛載時執(zhí)行一些業(yè)務(wù)A相關(guān)邏輯
})
this.$on('hook:updated', () => {
掛載時執(zhí)行一些業(yè)務(wù)A相關(guān)邏輯
})
this.$once('hook:beforeDestroy', () => {
掛載時執(zhí)行一些業(yè)務(wù)A相關(guān)邏輯
})
}
}
場景三
想要監(jiān)聽別人封裝好的組件(第三方組件)的生命周期,你不可能去第三方子組件的生命周期中寫代碼。
比如 element-ui 的button組件,在子組件渲染完成后,我想做某些邏輯變更。
<el-button type="primary" @hook:mounted="ButtonRender" :disabled="disabled">{{name}}</el-button>
export default {
name: 'Parents',
data: () => {
return {
name: 'dx',
disabled: true
};
},
methods: {
ButtonRender() {
this.disabled = false
this.name = 'yx'
}
}
}
所有生命周期執(zhí)行的順序
第一次渲染
父beforeCreate
父 hook:beforeCreate
父created
父 hook:created
父beforeMount
父 hook:beforeMount
子beforeCreate
子hook:beforeCreate
子created
子hook:created
子beforeMount
子hook:beforeMount
子mounted
子hook:mounted
父mounted
父 hook:mounted
更新時
父beforeUpdate
父hook:beforeUpdate
子beforeUpdate
子hook:beforeUpdate
子updated
子hook:updated
父updated
父hook:updated
組件摧毀時
父beforeDestroy
父hook:beforeDestroy
子beforeDestroy
子hook:beforeDestroy
子destroyed
子hook:destroyed
父destroyed
父hook:destroyed
以上內(nèi)容涉及到vue父子組件生命周期執(zhí)行順序的知識,但對于@hook:xxx來說,在xxx執(zhí)行后就會立即執(zhí)行@hook:xxx
總結(jié)
到此這篇關(guān)于vue2中@hook的解析與妙用的文章就介紹到這了,更多相關(guān)vue2 @hook妙用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
element?ui富文本編輯器的使用效果與步驟(quill-editor)
富文本編輯器在任何項目中都會用到,在Element中我們推薦vue-quill-editor組件,下面這篇文章主要給大家介紹了關(guān)于element?ui富文本編輯器的使用效果與步驟(quill-editor)的相關(guān)資料,需要的朋友可以參考下2022-10-10
Ant Design Vue全局對話確認(rèn)框(confirm)的回調(diào)不觸發(fā)
這篇文章主要介紹了Ant Design Vue全局對話確認(rèn)框(confirm)的回調(diào)不觸發(fā)問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-07-07
Vue.extend實現(xiàn)組件庫message組件示例詳解
這篇文章主要為大家介紹了Vue.extend實現(xiàn)組件庫message組件示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07
Vue3響應(yīng)式對象Reactive和Ref的用法解讀
這篇文章主要介紹了Vue3響應(yīng)式對象Reactive和Ref的用法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09
一文詳細(xì)聊聊vue3的defineProps、defineEmits和defineExpose
vue3官方文檔defineProps和defineEmits都是只能在scriptsetup中使用的編譯器宏,下面這篇文章主要給大家介紹了關(guān)于vue3的defineProps、defineEmits和defineExpose的相關(guān)資料,需要的朋友可以參考下2023-02-02

