什么 Hooks?請叫我 Composables !
Hello,大家好,我是 Sunday。
昨天跟一位同學(xué)聊天,說到:“在 Vue 中 hooks 是否可以使用 Vue 的生命周期?”
我一下就沒反應(yīng)過來 “Vue 中有 hooks 了嗎?”。后來才明白,人家那叫 Composables(組合式函數(shù))
1. 什么是 hooks?
hook 翻譯過來是鉤子的意思。hooks 作為復(fù)數(shù),直譯就是 多個鉤子,在開發(fā)領(lǐng)域中特指 鉤子函數(shù)。
在開發(fā)領(lǐng)域,最初的 hook 是和回調(diào)鉤子綁定的。比如我們常說的 git hooks 指的就是在 git 提交的時候所產(chǎn)生的多個回調(diào)鉤子函數(shù)。
圖片
不過,在 React 16.8 的版本之后,React 文檔中提到了 React Hooks 的概念。
圖片
React Hooks 與傳統(tǒng) hook 的概念不太相同,他表示的是:以 use 開頭的自定義函數(shù)
在 React 中,所有內(nèi)置的 Hooks 和社區(qū)約定的自定義 Hooks 函數(shù)都遵循以 use 開頭的命名規(guī)則
自此,hooks 的概念才進(jìn)入到大部分開發(fā)者的視野中。
2. Vue 中的 “hooks”
Vue 中嚴(yán)格來說 不存在 hooks 的概念。但是,卻有非常類似(也有人說是抄襲)的概念,這就是 Composables(組合式函數(shù))
“組合式函數(shù)”(Composables) 是一個利用 Vue 的組合式 API 來封裝和復(fù)用有狀態(tài)邏輯的函數(shù)。
與 React 相同,它(Composables)的命名也要求 以 use 開頭的駝峰標(biāo)識,而返回值則盡量返回 以 ref 包裹的響應(yīng)式數(shù)據(jù)
在 Vue 的官方文檔中,描述了 Composables 與 React Hooks 的關(guān)系:
圖片
3. Composables 示例
接下來,我們就通過一個 鼠標(biāo)跟蹤器示例,來更加清楚的了解下 Composables 的應(yīng)用場景。
3.1 監(jiān)聽鼠標(biāo)位置的直接寫法
如果我們要直接在組件中使用組合式 API 實(shí)現(xiàn)鼠標(biāo)跟蹤功能,它的代碼會是這樣:
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
const x = ref(0)
const y = ref(0)
function update(event) {
x.value = event.pageX
y.value = event.pageY
}
onMounted(() => window.addEventListener('mousemove', update))
onUnmounted(() => window.removeEventListener('mousemove', update))
</script>
<template>Mouse position is at: {{ x }}, {{ y }}</template>
這個代碼邏輯并不復(fù)雜:
- 首先我們使用 ref 定義了兩個響應(yīng)式數(shù)據(jù) x、y
- 然后在 onMounted 和 onUnmounted 生命周期中,完成事件的掛載和銷毀
- 通過 update 方法,修改響應(yīng)式數(shù)據(jù)的值,并展示在頁面中
這樣的代碼作用在單獨(dú)的組件里,如果想要 復(fù)用 就比較麻煩了。因此,就可以使用 Composables
3.2 使用 Composables
基于 Composables 封裝該邏輯:
// mouse.js
import { ref, onMounted, onUnmounted } from 'vue'
// 按照慣例,組合式函數(shù)名以“use”開頭
export function useMouse() {
// 被組合式函數(shù)封裝和管理的狀態(tài)
const x = ref(0)
const y = ref(0)
// 組合式函數(shù)可以隨時更改其狀態(tài)。
function update(event) {
x.value = event.pageX
y.value = event.pageY
}
// 一個組合式函數(shù)也可以掛靠在所屬組件的生命周期上
// 來啟動和卸載副作用
onMounted(() => window.addEventListener('mousemove', update))
onUnmounted(() => window.removeEventListener('mousemove', update))
// 通過返回值暴露所管理的狀態(tài)
return { x, y }
}
根據(jù)以上代碼所以,我們可知:
- Composables 中,應(yīng) 盡量使用 ref
- Composables 中,生命周期可正常調(diào)用,就像我們寫普通的 js 一樣
下面是它在組件中使用的方式:
<script setup>
import { useMouse } from './mouse.js'
const { x, y } = useMouse()
</script>
<template>Mouse position is at: {{ x }}, {{ y }}</template>