持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情
本文主要通过代码来展示,如何封装选项式Api的生命周期钩子函数(骚操作)和组合式Api的生命周期钩子函数,以及他们之间的不同之处。
1、一个组件中同时使用组合式api和选项式api
相信玩过vue3的同学们,大部分应该都了解或者使用过vue2吧,那么对选项式的api就不会陌生,或者你不熟悉名字,看一下下面的代码就非常清楚了。
<template>
<div>
Test
</div>
</template>
<script>
// 选项式api代码
export default {
name: 'Test',
mounted() {
console.log('选项是Api: mounted 第一个')
},
mounted() {
console.log('选项是Api: mounted 第二个')
},
}
</script>
<script setup>
// 组合式api代码
import { onMounted } from 'vue'
onMounted(() => {
console.log('组合式Api:Setup中的onMounted 第一个')
})
onMounted(() => {
console.log('组合式Api:Setup中的onMounted 第二个')
})
</script>
复制代码
执行的结果是
// 组合式Api:Setup中的onMounted 第一个
// 组合式Api:Setup中的onMounted 第二个
// 选项是Api: mounted 第二个
复制代码
可以发现组合式Api的生命周期在Vue3中会顺序执行,而选项式Api的生命周期钩子只会执行最后一个,也就是存在覆盖的问题,但是在选项式Api中可以设置组件的name属性。
2、看一下vue-router中的钩子函数
<template>
<div>
<button type="button" class="btn btn-primary" @click="jumpClick">跳转到详情页</button>
</div>
</template>
<script>
export default {
name: 'Test',
beforeRouteEnter(to, from, next) {
next(vm => {
console.log('选项式Api:vue-router中的beforeRouteEnter钩子函数')
});
},
// beforeRouteLeave(to, from, next) {
// next(vm => {
// console.log('选项式Api:vue-router中的beforeRouteEnter钩子函数')
// });
// },
}
</script>
<script setup>
import { onMounted } from 'vue'
import { useRouter, onBeforeRouteLeave } from 'vue-router'
const router = useRouter()
onBeforeRouteLeave ((to, from) => {
console.log('组合式Api:vue-router中的onBeforeRouteLeave')
})
const jumpClick = () => {
router.push('test-detail')
}
</script>
复制代码
刷新页面后,页面中只有一个按钮,并查看控制台console.log,你可以发现选项式api中的beforeRouteEnter
钩子函数执行了。这个钩子函数比较特殊。在渲染组件前调用,也就是组件实例还没被创建。 点击按钮后跳转到另外一个测试页面,然后可以看到控制台执行了,组合式Api中的 onBeforeRouteLeave
钩子函数的console.log。
在选项式Api中我注释了一段代码: 写在这里不执行的,在下面setup生命周期执行是没问题的,现在还不清楚是不是我代码写的那里有什么问题????
3、封装组合式Api中的钩子函数
<script setup>
import { onMounted } from 'vue'
import { useRouter, onBeforeRouteLeave } from 'vue-router'
import { useCompositionHooks } from '@/hooks/useHooks'
onMounted(() => {
console.log('在本组件执行,组合式Api: onMounted')
})
const router = useRouter()
onBeforeRouteLeave ((to, from) => {
console.log('组合式Api:vue-router中的onBeforeRouteLeave')
})
useCompositionHooks()
const jumpClick = () => {
router.push('test-detail')
}
</script>
复制代码
以及useHooks文件中的封装
export function useCompositionHooks() {
onMounted(() => {
console.log('封装起来的组合式Api: onMounted')
})
onBeforeRouteLeave ((to, from) => {
console.log('封装起来的组合式Api:vue-router中的onBeforeRouteLeave')
})
}
复制代码
就是添加了两个钩子函数的封装,我们来看看执行情况
// 在本组件执行,组合式Api: onMounted
// 封装起来的组合式Api: onMounted
复制代码
再来看一下点击跳转按钮的执行
//组合式Api:vue-router中的onBeforeRouteLeave
// 封装起来的组合式Api:vue-router中的onBeforeRouteLeave
复制代码
在组合式api的执行过程中,会根据代码的执行顺序进行,钩子函数可多次注入,但会根据代码前后顺序调用。
4、封装选项式api的钩子函数(骚操作一下)
<script>
import { useOptionsHooks } from "@/hooks/useHooks"
const useOptions = useOptionsHooks('test')
export default {
beforeRouteEnter(to, from, next) {
next(vm => {
console.log('在本组件执行,选项式Api: beforeRouteEnter')
});
},
...useOptions,
}
</script>
复制代码
再来看一下useHooks文件中的封装
export function useOptionsHooks(componentName: string) {
return {
name: componentName,
beforeRouteEnter(to: any, from: any, next: any) {
next(() => {
console.log('封装选项式Api:vue-router中的beforeRouteEnter钩子函数')
});
},
}
}
复制代码
执行结果如下,页面刷新后
// 封装选项式Api:vue-router中的beforeRouteEnter钩子函数
复制代码
骚操作:通过对外封装一个useOptionsHooks, return返回的就是选项式api使用的钩子。然后再export default 中 通过对函数调用后的对象进行解构展开
如果我们将export default中的代码位置进行调换
export default {
...useOptions,
beforeRouteEnter(to, from, next) {
next(vm => {
console.log('在本组件执行,选项式Api: beforeRouteEnter')
});
},
}
复制代码
执行结果如下
// 在本组件执行,选项式Api: beforeRouteEnter
复制代码
会根据当前代码的顺序位置,后面的代码如果包含前面的钩子函数,则会把前面声明的钩子函数内容覆盖掉。
5、总结
- vue3组合式api,本身封装通用性就更强,现在对钩子函数的独立封装又有了新的认识
- vue3如果想设置组件的name名称,则可以在该组件位置,添加一个选项式api包裹设置name即可。
- 如果要使用 vue-router中的 beforeRouteEnter钩子函数,就得在选项式api中进行声明和使用。
- vue3 选项