Vue3学习(6)-Vue3的生命周期和自定义hook

发布于:2025-06-15 ⋅ 阅读:(19) ⋅ 点赞:(0)

1. Vue3生命周期

  • 创建阶段:setup
  • 挂载阶段:onBeforeMountonMounted
  • 更新阶段:onBeforeUpdateonUpdated
  • 卸载阶段:onBeforeUnmountonUnmounted

常用的钩子: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>

注意:

  1. 需显式导入钩子(如 import { onMounted } from ‘vue’)。
  2. setup() 替代了 beforeCreate 和 created,逻辑集中在此函数中组织。
  3. 钩子函数名增加前缀 on(如 onMounted)。

2. 自定义hook

  • 定义:本质是一个函数,把setup函数中使用的Composition API进行了封装。
  • 自定义hook的优势:复用代码, 让setup中的逻辑更清楚易懂。

2.1 自定义 Hook 的本质与核心价值

  1. ​逻辑复用与解耦​
    将组件中的状态逻辑(如数据获取、事件监听、状态管理)提取为独立函数,避免重复代码。
    例:useMousePosition 封装鼠标坐标追踪逻辑,供多个组件调用。
  2. ​组合性​
    多个 Hook 可组合使用(如 useAdd + useAverage),构建复杂逻辑链。
  3. ​替代 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>

网站公告

今日签到

点亮在社区的每一天
去签到