vue 中監(jiān)聽生命周期事件的操作方式
vue 中監(jiān)聽生命周期事件
vue2 提供了一些生命周期事件的方式,在組件銷毀后觸發(fā)一個(gè)事件,父組件可監(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)
}
}這種寫法存在兩個(gè)小問題:
- 添加了額外的變量
onResize,感覺有點(diǎn)多余; - 監(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)
})
}
}凡在銷毀時(shí)執(zhí)行的操作,都可這樣優(yōu)化。
有人說方式1的問題不大,也沒有優(yōu)化多少,似乎沒有多少用。
再看一個(gè)場景:
希望在子組件掛載時(shí)通知父組件
通常的寫法:
// 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),如果是第三方組件呢?
上面的方法就無招了。
生命周期事件可以解決這個(gè)問題:
在模板上監(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)聽第三方組件的生命周期時(shí)很有用。
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 對(duì)象,通過它,可獲取到
el、props、ref等組件的重要屬性。
比如,可獲取
el,然后手動(dòng)修改它,以達(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
項(xiàng)目中 animate.css 和 element-plus 一起使用,animate 的 [disabled] 樣式屬性權(quán)重太高,導(dǎo)致 element-plus 分頁有禁用樣式。

可以在分頁組件掛載和更新后移除 disabled 屬性,使用 onVnodeMounted 和 onVnodeUpdated 事件實(shí)現(xiàn)。
<ElPagination
onVnodeMounted={removePaginationDisabled}
onVnodeUpdated={removePaginationDisabled} />removePaginationDisabled 的參數(shù)是一個(gè) vNode 對(duì)象,可通過
el屬性拿到 html 模板,然后手動(dòng)修改它。
vue3 父子組件的生命周期的執(zhí)行順序是怎樣的?
通過兩個(gè)組件,可以觀察到:
<!-- 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 # 類似兩個(gè)圈,或者洋蔥模型 # 父組件掛載階段先進(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 # 也類似兩個(gè)圈 父組件先進(jìn)入更新階段,后更新

規(guī)律:父子組件的生命周期執(zhí)行順序類似一個(gè)兩個(gè)圈,setup beforeXXX 在前方,XXXed 在后方,子組件的圈在內(nèi)部。
生命周期事件在相應(yīng)的生命周期鉤子執(zhí)行后觸發(fā),但是
vue:beforeUnmount先于onBeforeUnmount執(zhí)行,這點(diǎn)特殊。
小結(jié)
- vue2 監(jiān)聽生命周期事件的方式:
@hook:hookName。 - vue3 的方式
@vue:hookName或者onVnodeHookName。 - vue3 的父子組件每個(gè)階段的生命周期執(zhí)行順序是兩個(gè)圈,setup onBeforeXXX 在前方,XXXed 在后方,子組件的圈在內(nèi)部。
vue:hookName在 vue3 的文檔中沒有找到,說明這些 API 可能不穩(wěn)定,不要頻繁使用它們。
到此這篇關(guān)于vue 中監(jiān)聽生命周期事件的文章就介紹到這了,更多相關(guān)vue監(jiān)聽生命周期事件內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript之實(shí)現(xiàn)一個(gè)簡單的Vue示例
這篇文章主要介紹了JavaScript之實(shí)現(xiàn)一個(gè)簡單的Vue示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-01-01
基于Vue.js實(shí)現(xiàn)一個(gè)完整的登錄功能
在現(xiàn)代Web應(yīng)用中,用戶登錄功能是一個(gè)核心模塊,它不僅涉及到用戶身份驗(yàn)證,還需要處理表單驗(yàn)證、狀態(tài)管理、接口調(diào)用等多個(gè)環(huán)節(jié),本文將基于一個(gè)Vue.js項(xiàng)目中的登錄功能實(shí)現(xiàn),深入解析其背后的技術(shù)細(xì)節(jié),幫助開發(fā)者更好地理解和實(shí)現(xiàn)類似功能,需要的朋友可以參考下2025-02-02
vue-cli項(xiàng)目使用vue-picture-preview圖片預(yù)覽組件方式
這篇文章主要介紹了vue-cli項(xiàng)目使用vue-picture-preview圖片預(yù)覽組件方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09
Vue 實(shí)現(xiàn)前端權(quán)限控制的示例代碼
這篇文章主要介紹了Vue 實(shí)現(xiàn)前端權(quán)限控制的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07
基于vue-cli npm run build之后vendor.js文件過大的解決方法
今天小編就為大家分享一篇基于vue-cli npm run build之后vendor.js文件過大的解決方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-09-09

