vue 中监听生命周期事件
- 常见的添加自定义事件的写法
- 希望在子组件挂载时通知父组件
- 在模板上监听组件生命周期
- vue3 有类似的写法吗?
- jsx 中如何监听 vue3 组件的生命周期事件呢?
- vue3 父组件组件的生命周期的执行顺序是什么?
- 小结
vue2 提供了一些生命周期事件的方式,可以在组件销毁时执行一些操作。
命名为 hook:lifeHook
,比如 hook:beforeDestroy
。
常见的添加自定义事件的写法
{mounted() {this.onResize = () => {console.log('onResize')}window.addEventListener('resize', this.onResize)},beforeDestroy() {window.removeEventListener('resize', this.onResize)}
}
这种写法存在两个小问题:
- 添加了额外的变量
onResize
,感觉有点多余; - 监听
resize
的逻辑分散在不同的生命周期中,不好维护。
使用监听生命周期事件的方式优化:
{mounted() {const onResize = () => {console.log('onResize')}window.addEventListener('resize', onResize)// hook:lifeHook $once 只执行一次this.$once('hook:beforeDestroy', () => {window.removeEventListener('resize', onResize)})}
}
凡在销毁时执行的操作,都可这样优化。
有人说方式1的问题不大,也没有优化多少,似乎没有多少用。
再看一个场景:
希望在子组件挂载时通知父组件
通常的写法:
// SonComponent.vue
{mounted() {this.$emit('mounted')}
}
在父组件中监听子组件触发的事件:
<template><div><SonComponent @mounted="onMounted" /></div>
</template><script>export default {methods: {onMounted() {console.log('onMounted')}}}
</script>
问题解决了,但是 SonComponent 是自己写的组件,具有完全的控制权,如果是第三方组件呢?
上面的方法就无招了。
生命周期事件可以解决这个问题:
在模板上监听组件生命周期
<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>
生命周期事件在监听第三方组件的生命周期时很有用。
vue3 有类似的写法吗?
vue3 提供了 vue:hook
的写法,比如 vue:mounted
。
<script setup lang="ts">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
不再支持,可使用第三方库解决。
这些生命周期时间抛出的数据是组件的 vNode 对象。
jsx 中如何监听 vue3 组件的生命周期事件呢?
vue3 提供了 onVnodeXXX
方法,可以监听组件的生命周期事件。
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 可能不稳定,不要频繁使用它们。
vue3 父组件组件的生命周期的执行顺序是什么?
vue3 的生命周期执行顺序是:
首次渲染
parent setup
parent onBeforeMount
parent vue:beforeMountson setupson onBeforeMountson vue:beforeMountson onMountedson vue:mounted
parent onMounted
# 类似两个圈,或者洋葱模型
# 父组件挂载阶段先进入后挂载
销毁
Parent onBeforeUnmountSon vue:beforeUnmount # !生命周期事件先触发Son onBeforeUnmountSon onUnmountedSon vue:unmounted # ! 生命周期事件后触发
Parent onUnmounted
# 也类似洋葱模型
更新
Parent onBeforeUpdateSon onBeforeUpdateSon vue:beforeUpdateSon updatedSon vue:updated
Parent onUpdated
# 也类似两个圈 父组件先进入更新阶段,后更新
规律:父子组件的生命周期执行顺序类似一个两个圈,setup beforeXXX 在前方,XXXed 在后方,子组件的圈在内部。
生命周期事件在相应的生命周期钩子执行后触发,但是
vue:beforeUnmount
先于onBeforeUnmount
执行,这点特殊。
小结
- vue2 监听生命周期事件的方式:
@hook:lifeHook
。 - vue3 的方式
@vue:hook
或者onVnodeHook
。 - vue3 vue组件每个阶段的生命周期执行顺序是两个圈,setup beforeXXX 在前方,XXXed 在后方,子组件的圈在内部。