1. Hooks 定义
官方对自定义 hook 定义:在 Vue 应用的概念中,“组合式函数” (Composables) 是一个利用 Vue 组合式 API 来封装和复用有状态逻辑的函数。
其实 Hooks 本质是一个函数,把 setup 函数中使用的 Composition API 进行了封装。自定义 Hooks 可以复用代码, 让 setup 中的逻辑更清楚易懂。
2. 如何自定义Hooks
自定义Hooks是为了处理组件逻辑的一种模式。它可以让我们在不使用组件之间复制粘贴代码的情况下重用状态逻辑。自定义hooks是简单的javaScrpt函数,但是在使用是,我们要遵循两个重要(不成文)的命名约定:①以use开头。②可以调用其他的hooks。
3. 如何编写自定义Hooks
在src文件夹下新建一个hooks文件夹,用于统一存放程序中用到的hooks代码。
建一个useCounter.js, 做为自定义hook,它使用reactive创建一个响应式的状态对象,并返回一个包含count属性和increment方法的对象
import { reactive,toRefs } from "vue";
export const useCounter = ()=> {
const state=reactive({
count:0
})
function increment() {
state.count++
}
return {
...toRefs(state),
increment
}
}
在组件中引入useCounter,在setup函数中调用
<template>
{{ count }}
<button @click="increment">add</button>
</template>
<script setup lang='ts'>
import { useCounter } from '@/hooks/useCounter.js';
const {count,increment} = useCounter()
</script>
使用自定义Hooks的组件中使用import将我们创建Hooks代码引入,然后调用里面的属性和方法即可
4. 在复杂的场景中使用Hooks
在实际应用中,自定义hooks的使用会比我们上面的示例复杂一些,常用的使用场景包括处理网络请求和状态管理。为了更好的进行代码维护,官方也推荐我们尽可能地把状态和逻辑分离到单一的切面中,单独组织出一个hooks文件,存放整个应用或某个模块中可以重用的业务逻辑。
在处理复杂业务逻辑的时候,有时需要使用某个特定的原生事件,例如:scroll,resize等。可以把一些公共的原生事件处理逻辑封装到一个自定义hooks中,并将其于组件的某个特定属性进行绑定。
例:多个页面监听鼠标滚动时的scrollTop值,新建一个useScroll.js
import {ref,onMounted,onUnmounted,} from 'vue'
export default function useScroll() {
const scrollTop=ref(0)
const handleScroll=(e)=>{
scrollTop.value=e.target.documentElement.scrollTop
}
onMounted(() => {
window.addEventListener('scroll', handleScroll)
}),
onUnmounted(() => {
window.removeEventListener('scroll', handleScroll)
})
return {
scrollTop
}
}
需要获取scrollTop值的组件中引入useScroll.js,获取scrollTop并处理相关业务,
<template>
{{ count }}
<button @click="increment">add</button>
<br>
<div>{{ scrollTop }}</div>
</template>
<script setup lang='ts'>
import useCounter from '@/hooks/useCounter.js';
import useScroll from '@/hooks/useScroll.js';
const { scrollTop } = useScroll()
console.log(scrollTop);
const {count,increment} = useCounter()
</script>
<style>
div {
height:500px;
scroll-margin-top:10px;
}
</style>
5. 使用Hooks的优点
- 提高组件代码的可读性和可维护性。
- 简化代码逻辑,减少代码复杂度。
- 消除“渲染属性”或“渲染组件”等传统的高阶组件模式的使用。
- 封装逻辑,使得组件可以更好地适应重用。
- 用Hook,不需要编写类组件,可以更好的使用javaScript的函数式风格,提高代码扩展性