Hooks技术最早是由React团队的Sophie Alpert和Dan Abramov在2018年提出来的。最初是为了解决React类组件中状态逻辑复用的问题提出来的。在React使用类组件时,为了复用状态逻辑,需要使用高阶组件或者Render Props等方式,这些方式会增加代码的复杂度和维护成本。而Hooks技术是使用特定函数来“钩到”React的state和生命周期等特性的技术。它可以让我们在函数组件中使用state以及其他的React特性,替代传统的类组件或高阶组件等方式。
Vue 3.0中没有直接引入和 React Hooks 相同的概念,尽管Vue 3.0引入了一个与Hooks类似的API,称为Composition API,但两者概念略有不同。Composition API旨在提供更好的代码组织和复用逻辑的方式,它是一组API,使得在Vue 3 应用程序中使用基于逻辑的组合更方便,并尝试解决使用Options API时遇到的一些限制和缺陷。
虽然在vue3的官方文档中并没有提及使用Hooks技术,但是我们在vue3中的Composition API中却时刻能看到Hooks的影子,比如vue3中的onMounted、onUpdated、onUnmounted等都可以看做是Hooks。这些Hooks可以帮助我们在函数组件中访问Vue的生命周期和状态方法。
自定义Hooks是为了处理组件逻辑的一种模式。它可以让我们在不使用组件之间复制粘贴代码的情况下重用状态逻辑。自定义hooks是简单的JavaScript函数,但是在使用是,我们要遵循两个重要(不成文)的命名约定:
如果我们编写的代码符合这两个约定,那么我们就可以编写自己的hook,然后在Vue组件中使用它。一般我们会在src文件夹下新建一个hooks文件夹,用于统一存放程序中用到的hooks代码。
下面结合实例我们来写一个简单的hooks,我们在src文件夹下新建hooks文件夹后,在里面新建一个useCounter.js文件,代码如下:
import { reactive,toRefs } from "vue";
export default function useCounter() {
const state = reactive({
count:0
})
function increment() {
state.count++
}
return {
...toRefs(state),
increment
}
}
这段代码定义了一个名为useCounter.js的文件作为自定义hook,它使用reactive创建一个响应式的状态对象,并返回一个包含count属性和increment方法的对像。
下面我们在Vue组件中引入useCounter,然后在 setup 函数中调用它:
<template>
{{ count }}
<button @click="increment">add</button>
</template>
<script setup>
import useCounter from './hooks/useCounter';
const { count,increment } = useCounter()
</script>
<style scoped>
</style>
上面代码中,我们在App.vue中引入上面定义的钩子函数useCounter,解构出里面的count和increment就可以在模板找那个直接使用了,可以看到这种使用hooks的方式可以是代码非常简洁。
其实在上面什么是自定义Hooks的介绍中,我们已经编写了一个自定义Hooks,编写自定义hook简单说就是定义了一段暴露给我们使用的可复用的js代码片段,只要里面的代码逻辑正确,我们可以随意命名这段代码片段,但是,为了维护代码的可读性,我们在定义Hooks代码片段时,还是要遵循上面两条业界默认的命名规范约定,即:
下面以一个用于显示和隐藏模态框的钩子为例,我们再来编写一个自定义Hooks
在hooks文件夹新建useModal.js文件,编写代码如下:
import { ref } from "vue"
export default function useModal() {
const isModalVisible = ref(false)
const toggleModal = () => {
isModalVisible.value = !isModalVisible.value
}
return { isModalVisible, toggleModal }
}
这样我们就编写好了自定义Hooks
使用自定义Hooks也非常简单,我们只需要在需要使用自定义Hooks的组件中使用import将我们创建的Hooks代码引入,然后调用里面的属性和方法即可。
如上面我们定义的一个显示和隐藏模态框的钩子,我们就可以在App.vue组件中直接引入使用,代码如下:
<template>
{{ count }}
<button @click="increment">add</button>
<br>
{{ isModalVisible }}
<button @click="toggleModal">changeModel</button>
</template>
<script setup>
import useCounter from './hooks/useCounter';
import useModal from './hooks/useModal'
const { count,increment } = useCounter()
const { isModalVisible, toggleModal } = useModal()
</script>
<style scoped>
</style>
在实际应用中,自定义hooks的使用会比我们上面的示例复杂一些,常见的使用场景包括处理网络请求和状态管理。前面我们也提到了,为了更好的进行代码维护,我们为Hooks代码片段单独创建了一hooks文件夹,在Vue3中,为了更好的维护应用程序的状态,官方也推荐我们尽可能地把状态和逻辑分离到单一的切面中,单独组织出一个hooks文件,存放整个应用或某个模块中可以重用的业务逻辑。
下面我们再来实现一个注册特定的原生事件的Hooks
我们在处理复杂业务逻辑的时候,有时需要使用某个特定的原生事件,例如:scroll、resize等。我们就可以把这些公共的原生事件处理逻辑封装到一个自定义hooks中,并将其与组件的某个特定属性进行绑定。
比如我们有这样一个需求,需要在多个页面监听鼠标滚动时的scrollTop值,我们就可以在hooks文件夹新建useScroll.js,并编写下面代码:
import { ref,onMounted,onUnmounted} from 'vue'
export default function useScroll() {
const scrollTop = ref(0)
const handleScroll = (e) => {
console.log(e);
scrollTop.value = e.target.documentElement.scrollTop
}
onMounted(() => {
window.addEventListener('scroll', handleScroll)
})
onUnmounted(() => {
window.removeEventListener('scroll', handleScroll)
})
return {
scrollTop
}
}
然后,在我们需要获取scrollTop值的组件中引入useScroll.js,获取scrollTop并处理相关业务,这里我直接在App.vue中获取scrollTop并在页面中展示出来,代码如下:
<template>
{{ count }}
<button @click="increment">add</button>
<br>
{{ isModalVisible }}
<button @click="toggleModal">changeModel</button>
<br>
<br>
<div>
{{ scrollTop }}
</div>
</template>
<script setup>
import useCounter from './hooks/useCounter';
import useModal from './hooks/useModal'
import useScroll from './hooks/useScroll'
const { count,increment } = useCounter()
const { isModalVisible, toggleModal } = useModal()
const { scrollTop } = useScroll()
console.log(scrollTop);
</script>
<style scoped>
div {
height: 900px;
scroll-margin-top: 10px;
}
</style>
总之,自定义hooks不仅可以优化应用程序的代码结构,提高代码易读性,还可以增强应用程序的可维护性和扩展性。我们在实际的Vue3组件开发中,应该更加积极地使用自定义hooks,在提高代码质量和性能的同时,更好地满足业务需求。
好了,关于vue3中如何使用自定义Hooks,今天就先聊到这里,不知不觉已经2点了,洗洗睡了,喜欢的小伙伴点点你发财的小手,点赞关注加收藏哦!