vue 中監(jiān)聽生命周期事件的操作方式
vue 中監(jiān)聽生命周期事件
vue2 提供了一些生命周期事件的方式,在組件銷毀后觸發(fā)一個事件,父組件可監(jiān)聽到該事件,然后執(zhí)行某些操作。
命名為 hook:hookName
,前面的 hook:
是固定寫法,比如 hook:mounted
、 hook:beforeDestroy
。
常見的添加自定義事件的寫法
{ mounted() { this.onResize = () => { console.log('onResize') } window.addEventListener('resize', this.onResize) }, beforeDestroy() { window.removeEventListener('resize', this.onResize) } }
這種寫法存在兩個小問題:
- 添加了額外的變量
onResize
,感覺有點多余; - 監(jiān)聽
resize
的邏輯分散在不同的生命周期中,不好維護(hù)。
使用監(jiān)聽生命周期事件的方式優(yōu)化:
{ mounted() { const onResize = () => { console.log('onResize') } window.addEventListener('resize', onResize) // hook:lifeHook $once 只執(zhí)行一次 this.$once('hook:beforeDestroy', () => { window.removeEventListener('resize', onResize) }) } }
凡在銷毀時執(zhí)行的操作,都可這樣優(yōu)化。
有人說方式1的問題不大,也沒有優(yōu)化多少,似乎沒有多少用。
再看一個場景:
希望在子組件掛載時通知父組件
通常的寫法:
// SonComponent.vue { mounted() { this.$emit('mounted') } }
在父組件中監(jiān)聽子組件觸發(fā)的事件:
<template> <div> <SonComponent @mounted="onMounted" /> </div> </template> <script> export default { methods: { onMounted() { console.log('onMounted') } } } </script>
問題解決了,但是 SonComponent 是自己寫的組件,具有完全的控制權(quán),如果是第三方組件呢?
上面的方法就無招了。
生命周期事件可以解決這個問題:
在模板上監(jiān)聽組件生命周期
<template> <el-input @hook:mounted="onMounted" @hook:beforeDestroy="onBeforeDestroy" /> </template> <script> export default { methods: { onMounted() { console.log('el-input onMounted') }, onBeforeDestroy() { console.log('el-input onBeforeDestroy') } } } </script>
生命周期事件在監(jiān)聽第三方組件的生命周期時很有用。
vue3 生命周期事件嗎?
vue3 提供了 vue:hookName
的寫法,比如 vue:mounted
、 vue:unmounted
。
<script setup> import { ref } from 'vue' const input = ref('') function whenMounted(params) { console.log('whenMounted') console.log(params) } function whenBeforeUnmount() { console.log('whenBeforeUnmount') } function whenUpdated() { console.log('whenUpdated') } </script> <template> <el-input v-model="input" @vue:mounted="whenMounted" @vue:beforeUnmount="whenBeforeUnmount" @vue:updated="whenUpdated" /> </template>
this.$once
和this.$on
不再支持,可使用第三方庫解決。
這些生命周期事件拋出的數(shù)據(jù)是組件的 vNode 對象,通過它,可獲取到
el
、props
、ref
等組件的重要屬性。
比如,可獲取
el
,然后手動修改它,以達(dá)到某種目的。
jsx 中如何監(jiān)聽生命周期事件呢?
vue3 提供了 onVnodeHookName
方法,可以監(jiān)聽組件的生命周期事件。
onVnodeMounted
、 onVnodeBeforeUnmount
、 onVnodeUpdated
等。
export default function MyButton(props, { slots }) { function onVnodeMounted(vnode) { console.log('vnode mounted', vnode) } return ( <button onVnodeMounted={onVnodeMounted}> {{ default: () => slots.default?.() ?? '按鈕', }} </button> ) }
在模板中也是能使用這些方法的,但是不推薦,使用
@vue:hook
更直觀。
vue:hook
和onVnodeXXX
在 vue3 的文檔中沒有找到,說明這些 API 可能不穩(wěn)定,不要頻繁使用它們。
通過 vNode 操作 html
項目中 animate.css 和 element-plus 一起使用,animate 的 [disabled]
樣式屬性權(quán)重太高,導(dǎo)致 element-plus 分頁有禁用樣式。
可以在分頁組件掛載和更新后移除 disabled
屬性,使用 onVnodeMounted
和 onVnodeUpdated
事件實現(xiàn)。
<ElPagination onVnodeMounted={removePaginationDisabled} onVnodeUpdated={removePaginationDisabled} />
removePaginationDisabled 的參數(shù)是一個 vNode 對象,可通過
el
屬性拿到 html 模板,然后手動修改它。
vue3 父子組件的生命周期的執(zhí)行順序是怎樣的?
通過兩個組件,可以觀察到:
<!-- Parent.vue --> <script setup> import { onBeforeMount, onBeforeUnmount, onBeforeUpdate, onMounted, onUnmounted, onUpdated, ref, } from 'vue' import MyInput from './MyInput.vue' const myInput = ref('') function whenBeforeMount() { console.log('Son vue:beforeMount') } function whenMounted() { console.log('Son vue:mounted') } function whenBeforeUpdate() { console.log('Son vue:beforeUpdate') } function whenUpdated(vNode) { console.log('Son vue:updated') console.log(vNode) } function whenBeforeUnmount() { console.log('Son vue:beforeUnmount') } function whenUnmounted() { console.log('Son vue:unmounted') } console.log('Parent setup') onBeforeMount(() => { console.log('Parent onBeforeMount') }) onMounted(() => { console.log('Parent onMounted') }) onBeforeUpdate(() => { console.log('Parent onBeforeUpdate') }) onUpdated(() => { console.log('Parent onUpdated') }) onBeforeUnmount(() => { console.log('Parent onBeforeUnmount') }) onUnmounted(() => { console.log('Parent onUnmounted') }) </script> <template> <div class="init-options"> <p>this is p tag {{ myInput }}</p> <MyInput v-model="myInput" @vue:beforeMount="whenBeforeMount" @vue:mounted="whenMounted" @vue:beforeUpdate="whenBeforeUpdate" @vue:updated="whenUpdated" @vue:beforeUnmount="whenBeforeUnmount" @vue:unmounted="whenUnmounted" /> </div> </template>
MyInput.vue
作為子組件:
<script setup> import { onBeforeMount, onBeforeUnmount, onBeforeUpdate, onMounted, onUnmounted, onUpdated, ref, } from 'vue' console.log('Son setup') const props = defineProps({ modelValue: { type: String, default: '', }, }) const emits = defineEmits(['update:modelValue']) const input = ref(props.modelValue) onBeforeMount(() => { console.log('Son onBeforeMount') }) onMounted(() => { console.log('Son onMounted') }) onBeforeUpdate(() => { console.log('Son onBeforeUpdate') }) onUpdated(() => { console.log('Son updated') }) onBeforeUnmount(() => { console.log('Son onBeforeUnmount') }) onUnmounted(() => { console.log('Son onUnmounted') }) function onInput(e) { input.value = e.target.value emits('update:modelValue', e.target.value) } </script> <template> <div> <input :value="input" @input="onInput" /> <p>{{ input }}</p> </div> </template>
vue3 的父子生命周期執(zhí)行順序是:
組件掛載
parent setup parent onBeforeMount parent vue:beforeMount son setup son onBeforeMount son vue:beforeMount son onMounted son vue:mounted parent onMounted # 類似兩個圈,或者洋蔥模型 # 父組件掛載階段先進(jìn)入后掛載
銷毀
Parent onBeforeUnmount Son vue:beforeUnmount # !生命周期事件先觸發(fā) Son onBeforeUnmount Son onUnmounted Son vue:unmounted # ! 生命周期事件后觸發(fā) Parent onUnmounted # 也類似洋蔥模型
更新
Parent onBeforeUpdate Son onBeforeUpdate Son vue:beforeUpdate Son updated Son vue:updated Parent onUpdated # 也類似兩個圈 父組件先進(jìn)入更新階段,后更新
規(guī)律:父子組件的生命周期執(zhí)行順序類似一個兩個圈,setup beforeXXX 在前方,XXXed 在后方,子組件的圈在內(nèi)部。
生命周期事件在相應(yīng)的生命周期鉤子執(zhí)行后觸發(fā),但是
vue:beforeUnmount
先于onBeforeUnmount
執(zhí)行,這點特殊。
小結(jié)
- vue2 監(jiān)聽生命周期事件的方式:
@hook:hookName
。 - vue3 的方式
@vue:hookName
或者onVnodeHookName
。 - vue3 的父子組件每個階段的生命周期執(zhí)行順序是兩個圈,setup onBeforeXXX 在前方,XXXed 在后方,子組件的圈在內(nèi)部。
vue:hookName
在 vue3 的文檔中沒有找到,說明這些 API 可能不穩(wěn)定,不要頻繁使用它們。
到此這篇關(guān)于vue 中監(jiān)聽生命周期事件的文章就介紹到這了,更多相關(guān)vue監(jiān)聽生命周期事件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue實現(xiàn)表單數(shù)據(jù)的增刪改功能
這篇文章主要為大家詳細(xì)介紹了vue實現(xiàn)表單數(shù)據(jù)的增刪改功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-03-03vant使用datetime-picker組件設(shè)置maxDate和minDate的坑及解決
這篇文章主要介紹了vant使用datetime-picker組件設(shè)置maxDate和minDate的坑及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-12-12vue中axios利用blob實現(xiàn)文件瀏覽器下載方式
這篇文章主要介紹了vue中axios利用blob實現(xiàn)文件瀏覽器下載方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-05-05關(guān)于element-ui的隱藏組件el-scrollbar的使用
這篇文章主要介紹了關(guān)于element-ui的隱藏組件el-scrollbar的使用,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-05-05Vue 報錯TypeError: this.$set is not a function 的解決方法
這篇文章主要介紹了Vue 報錯TypeError: this.$set is not a function 的解決方法,分享給大家,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-12-12