Vue3学习(6)-Vue3的生命周期和自定义hook
1. Vue3生命周期
- 创建阶段:
setup
- 挂载阶段:
onBeforeMount
、onMounted
- 更新阶段:
onBeforeUpdate
、onUpdated
- 卸载阶段:
onBeforeUnmount
、onUnmounted
常用的钩子:onMounted
(挂载完毕)、onUpdated
(更新完毕)、onBeforeUnmount
(卸载之前)
示例代码:
<template><div class="person"><h2>当前求和为:{{ sum }}</h2><button @click="changeSum">点我sum+1</button></div>
</template><!-- vue3写法 -->
<script lang="ts" setup name="Person">import { ref, onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted } from 'vue'// 数据let sum = ref(0)// 方法function changeSum() {sum.value += 1}console.log('setup')// 生命周期钩子onBeforeMount(()=>{console.log('挂载之前')})onMounted(()=>{console.log('挂载完毕')})onBeforeUpdate(()=>{console.log('更新之前')})onUpdated(()=>{console.log('更新完毕')})onBeforeUnmount(()=>{console.log('卸载之前')})onUnmounted(()=>{console.log('卸载完毕')})
</script>
注意:
- 需显式导入钩子(如 import { onMounted } from ‘vue’)。
- setup() 替代了 beforeCreate 和 created,逻辑集中在此函数中组织。
- 钩子函数名增加前缀 on(如 onMounted)。
2. 自定义hook
- 定义:本质是一个函数,把
setup
函数中使用的Composition API
进行了封装。 - 自定义
hook
的优势:复用代码, 让setup
中的逻辑更清楚易懂。
2.1 自定义 Hook 的本质与核心价值
- 逻辑复用与解耦
将组件中的状态逻辑(如数据获取、事件监听、状态管理)提取为独立函数,避免重复代码。
例:useMousePosition 封装鼠标坐标追踪逻辑,供多个组件调用。 - 组合性
多个 Hook 可组合使用(如 useAdd + useAverage),构建复杂逻辑链。 - 替代 Vue 2 的 Mixin
解决 Mixin 的命名冲突和来源不清晰问题,通过函数显式调用和返回数据。
2.2 创建与使用步骤
1. 创建 Hook
- 命名规范:以 use 开头(如 useCounter)。
- 内部实现:
- 使用响应式 API(ref/reactive)管理状态。
- 使用生命周期钩子(onMounted/onUnmounted)处理副作用。
- 返回需暴露的变量或方法
示例1:
// useCounter.js
import { ref } from "vue";
export function useCounter(initialValue = 0) {const count = ref(initialValue);const increment = () => count.value++;return { count, increment };
}
示例2:
useSum.ts
中内容如下:
import {ref,onMounted} from 'vue'export default function(){let sum = ref(0)const increment = ()=>{sum.value += 1}const decrement = ()=>{sum.value -= 1}onMounted(()=>{increment()})//向外部暴露数据return {sum,increment,decrement}
}
useDog.ts
中内容如下:
import {reactive,onMounted} from 'vue'
import axios,{AxiosError} from 'axios'export default function(){let dogList = reactive<string[]>([])// 方法async function getDog(){try {// 发请求let {data} = await axios.get('https://dog.ceo/api/breed/pembroke/images/random')// 维护数据dogList.push(data.message)} catch (error) {// 处理错误const err = <AxiosError>errorconsole.log(err.message)}}// 挂载钩子onMounted(()=>{getDog()})//向外部暴露数据return {dogList,getDog}
}
2. 在组件中使用
导入 Hook 并调用,解构其返回值。
示例1:
<template><p>Count: {{ count }}</p><button @click="increment">+1</button>
</template>
<script setup>
import { useCounter } from "./hooks/useCounter";
const { count, increment } = useCounter(10); // 初始值 10
</script>
示例2:
<template><h2>当前求和为:{{sum}}</h2><button @click="increment">点我+1</button><button @click="decrement">点我-1</button><hr><img v-for="(u,index) in dogList.urlList" :key="index" :src="(u as string)"> <span v-show="dogList.isLoading">加载中......</span><br><button @click="getDog">再来一只狗</button>
</template><script lang="ts">import {defineComponent} from 'vue'export default defineComponent({name:'App',})
</script><script setup lang="ts">import useSum from './hooks/useSum'import useDog from './hooks/useDog'let {sum,increment,decrement} = useSum()let {dogList,getDog} = useDog()
</script>