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>error
console.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>