目录
1. 前言
在Vue3发布后,Composition API作为一个重要的特性,彻底改变了我们组织Vue组件代码的方式。其中,自定义Hooks的概念源自React,但Vue3对其进行了重新设计和优化,使其更加符合Vue的开发理念。本文将深入探讨Vue3中的自定义Hooks,帮助你掌握这个强大的代码复用工具。
2. 什么是Hooks
2.1 Hooks的定义
Hooks是一种特殊的函数,它可以让你在函数组件中使用状态和其他Vue特性。Vue3中的Hooks通常具有以下特征:
- 以"use"作为函数名称前缀
- 返回一个包含响应式数据或方法的对象
- 可以使用其他Hooks
- 遵循组合式函数的设计模式
2.2 为什么需要Hooks
- 代码复用问题
- Vue2中的mixins存在命名冲突
- 数据来源不清晰
- 逻辑复用不够灵活
- 组件逻辑组织问题
- 相关逻辑被选项API分散
- 代码维护困难
- 逻辑复用受限
2.3 与Vue2的区别
// Vue2 Mixin方式
const mouseMixin = {
data() {
return {
x: 0,
y: 0
}
},
mounted() {
window.addEventListener('mousemove', this.update)
},
methods: {
update(e) {
this.x = e.pageX
this.y = e.pageY
}
},
destroyed() {
window.removeEventListener('mousemove', this.update)
}
}
// Vue3 Hooks方式
function useMousePosition() {
const x = ref(0)
const y = ref(0)
const update = (e) => {
x.value = e.pageX
y.value = e.pageY
}
onMounted(() => {
window.addEventListener('mousemove', update)
})
onUnmounted(() => {
window.removeEventListener('mousemove', update)
})
return {
x, y }
}
3. Hooks的实现原理
3.1 响应式系统
Vue3的响应式系统是Hooks实现的基础,主要包括:
// 1. ref:适用于基础类型
const count = ref(0)
// 2. reactive:适用于对象类型
const state = reactive({
count: 0,
message: 'Hello'
})
// 3. computed:计算属性
const doubleCount = computed(() => count.value * 2)
// 4. watch:侦听器
watch(count, (newValue, oldValue) => {
console.log(`count changed from ${
oldValue} to ${
newValue}`)
})
3.2 生命周期集成
Hooks可以使用所有的生命周期钩子:
function useLifecycleLogger() {
onBeforeMount(() => {
console.log('组件即将挂载')
})
onMounted(() => {
console.log('组件已挂载')
})
onBeforeUpdate(() => {
console.log('组件即将更新')
})
onUpdated(() => {
console.log('组件已更新')
})
onBeforeUnmount(() => {
console.log('组件即将卸载')
})
onUnmounted(() => {
console.log('组件已卸载')
})
}
3.3 依赖注入系统
Hooks可以与provide/inject配合使用:
// 在父组件中
function useThemeProvider() {
const theme = ref('light')
provide('theme', theme)
const toggleTheme = () => {
theme.value = theme.value === 'light' ? 'dark' : 'light'
}
return {
theme,
toggleTheme
}
}
// 在子组件中
function useTheme() {
const theme = inject('theme')
if (!theme) {
throw new