当前位置: 首页 > ai >正文

Vue3 生命周期与Hooks

一、Vue3 生命周期全览

组件的生命周期是由一系列的钩子函数组成的,这些钩子在组件的不同创建和销毁阶段被调用。这些生命周期钩子提供了在特定时刻添加自定义行为的机会,例如在组件挂载到DOM后或数据更新前后执行代码。

Options API 与 Composition API 对照表

Options APIComposition API触发时机
beforeCreate无需映射在 setup() 之前执行
created无需映射在 setup() 之前执行
beforeMountonBeforeMount挂载开始之前
mountedonMounted挂载完成后
beforeUpdateonBeforeUpdate响应式数据变化导致重新渲染前
updatedonUpdated重新渲染完成后
beforeUnmountonBeforeUnmount组件卸载前
unmountedonUnmounted组件卸载后
errorCapturedonErrorCaptured捕获子孙组件错误时

二、Composition API 生命周期使用

基础示例

<script setup>
import { onBeforeMount,onMounted,onBeforeUpdate,onUpdated,onBeforeUnmount,onUnmounted 
} from 'vue'// 组件挂载阶段
onBeforeMount(() => {console.log('挂载前 - DOM 尚未创建')
})onMounted(() => {console.log('挂载完成 - 可访问 DOM')window.addEventListener('resize', handleResize)
})// 组件更新阶段
onBeforeUpdate(() => {console.log('数据变化,即将重新渲染')
})onUpdated(() => {console.log('重新渲染完成')
})// 组件卸载阶段
onBeforeUnmount(() => {console.log('组件即将卸载')
})onUnmounted(() => {console.log('组件已卸载')window.removeEventListener('resize', handleResize)
})function handleResize() {console.log('窗口大小变化')
}
</script>

三、关于 Hooks

在Vue3中,Hooks是基于Composition API实现的一组可复用的函数。这些函数可以“钩入”Vue组件的生命周期,让我们能够在组件的不同生命周期阶段执行特定的逻辑。

1. Hooks的实现原理

在Vue3中,Hooks通过setup函数来使用。setup函数是Vue3组件中的一个新的生命周期函数,它在组件实例被创建之前调用,并且接收两个参数:propscontext。在setup函数中,我们可以定义和返回组件中需要使用的响应式数据、方法、计算属性等,而这些都可以通过Hooks来实现。

2 .Hooks的使用场景

  1. 逻辑复用:当多个组件需要共享相同的逻辑时,我们可以将这些逻辑封装成一个Hook,然后在需要的组件中导入并使用它。这样可以避免代码重复,提高代码的复用性。

  2. 逻辑拆分:对于复杂的组件,我们可以使用Hooks将组件的逻辑拆分成多个独立的函数,每个函数负责处理一部分逻辑。这样可以使组件的代码更加清晰、易于维护。

  3. 副作用管理Hooks中的函数可以访问组件的响应式数据,并且可以在组件的生命周期中执行副作用操作(如定时器、事件监听等)。通过使用Hooks,我们可以更好地管理这些副作用操作,确保它们在组件卸载时得到正确的清理。


四、自定义 Hook 开发指南

1. 鼠标位置跟踪 Hook

// hooks/useMousePosition.js
import { ref, onMounted, onUnmounted } from 'vue'export function useMousePosition() {const x = ref(0)const y = ref(0)const updatePosition = (e) => {x.value = e.clientXy.value = e.clientY}onMounted(() => {window.addEventListener('mousemove', updatePosition)})onUnmounted(() => {window.removeEventListener('mousemove', updatePosition)})return { x, y }
}// 组件中使用
<script setup>
import { useMousePosition } from './hooks/useMousePosition'const { x, y } = useMousePosition()
</script><template>鼠标位置:{{ x }}, {{ y }}
</template>

2. 异步数据请求 Hook

// hooks/useFetch.js
import { ref, onBeforeUnmount } from 'vue'export function useFetch(url) {const data = ref(null)const error = ref(null)const loading = ref(false)let abortController = new AbortController()const fetchData = async () => {try {loading.value = trueconst response = await fetch(url, { signal: abortController.signal })data.value = await response.json()} catch (err) {error.value = err} finally {loading.value = false}}onBeforeUnmount(() => {abortController.abort()})return {data,error,loading,fetchData}
}// 组件中使用
<script setup>
import { useFetch } from './hooks/useFetch'const { data, loading, error, fetchData } = useFetch('/api/data')onMounted(() => {fetchData()
})
</script>

五、最佳实践与常见问题

1. 生命周期使用原则

  • 在 onMounted 中访问 DOM/初始化第三方库

  • 在 onUnmounted 中清理副作用(定时器、事件监听)

  • 避免在 onUpdated 中修改状态(可能导致无限循环)

2. 自定义 Hook 规范

  • 命名以 use 开头(如 useDarkMode

  • 单一职责原则(一个 Hook 只解决一个问题)

  • 返回响应式数据时使用 toRefs

    return toRefs(reactive({ x, y }))

3. 常见问题解决
Q:如何在 setup 中访问 this?

  • 不需要也不应该访问 this,所有上下文通过 Composition API 获取

Q:多个 Hook 之间如何共享状态?

// 共享状态 Hook
export function useCounter(initialValue = 0) {const count = ref(initialValue)const increment = () => count.value++return {count,increment}
}// 组件 A
const { count: countA } = useCounter()// 组件 B
const { count: countB } = useCounter(10)

Q:如何处理异步操作的竞态条件?

// 在 Hook 中添加请求标识
let requestId = 0const fetchData = async () => {const currentId = ++requestIdconst res = await fetch(url)if (currentId === requestId) {// 处理有效响应}
}

六、高级应用场景

1. 组合多个 Hook

// 组件逻辑
const { user } = useUser()
const { posts, loading } = usePosts(user.value.id)
const { width } = useWindowSize()

2. 带参数的动态 Hook

// 根据路由参数变化的 Hook
export function useRouteData() {const route = useRoute()const id = computed(() => route.params.id)const { data, fetch } = useFetch(`/api/${id.value}`)watch(id, fetch, { immediate: true })return { data }
}

3. 生命周期可视化调试

// 开发环境专用 Hook
export function useLifecycleLogger(name) {if (process.env.NODE_ENV === 'development') {onBeforeMount(() => console.log(`${name} - beforeMount`))onMounted(() => console.log(`${name} - mounted`))// 其他生命周期同理...}
}

七、TypeScript 增强示例

1. 类型化生命周期

interface Position {x: numbery: number
}export function useMousePosition(): {x: Ref<number>y: Ref<number>
} {// 实现同上
}

2. 泛型请求 Hook

export function useFetch<T>(url: string) {const data = ref<T | null>(null)// 其他逻辑...return { data }
}// 使用示例
interface User {id: numbername: string
}const { data } = useFetch<User[]>('/api/users')

http://www.xdnf.cn/news/2032.html

相关文章:

  • C语言----函数栈帧讲解
  • Flink 系列之七 - Data Stream API的源算子原理
  • Codeforces Round 1020 (Div. 3)
  • 17.ArkUI Slider的介绍和使用
  • 免费的车牌势识别系统
  • 电商数据中台架构:淘宝 API 实时采集与多源数据融合技术拆解
  • Chrmo手动同步数据
  • 在虚拟机中安装Linux详细教程
  • PyQt6基础_QTableWidget
  • MSVCP140.dll丢失的解决方法:详细修复指南进一步了解MSVCP140.dll
  • SCI论文结构笔记
  • 【鸿蒙HarmonyOS】深入理解一端开发,多端部署
  • WINDOWS 下Maven 安装及配置教程
  • javaweb-cook-会话
  • 力扣热题——统计最大组的数目
  • 黑马Redis(三)黑马点评项目
  • 【昇腾】【训练】800TA2-910B使用LLaMA-Factory训练Qwen
  • 系统架构师2025年论文《微服务架构3》
  • 软件开发管理制度,项目研发制度,项目管理制度
  • 解决Spring Boot多模块自动配置失效问题
  • 如何把两个视频合并成一个视频?无需视频编辑器即可搞定视频合并
  • 【Java面试笔记:进阶】19.Java并发包提供了哪些并发工具类?
  • linux基础操作1------(文件命令)
  • STM32系列官方标准固件库的完整下载流程
  • MySql 数据 结构 转为SqlServer (简单)
  • WSL2-自定义安装
  • LLM数学推导——Transformer问题集——注意力机制——稀疏/高效注意力
  • Kafka与Spark-Streaming
  • 7.0 sharpScada的sql数据的安装
  • Oracle Recovery Tools修复ORA-00742、ORA-600 ktbair2: illegal inheritance故障