云计算百科
云计算领域专业知识百科平台

Vue笔记(十六)--自定义Hook

          这一节了解一下Vue3中的自定义Hook,它也叫组合式函数,本质就是抽离出来、可复用的setup逻辑函数,约定以use开头命名,简单总结如下:

自定义Hook本身不是 API,但是内部一般会使用下面这些Vue API:
1. ref:定义基础响应式数据
2. reactive:对象类型响应式
3. computed:计算属性
4. watch/watchEffect:监听数据变化、执行副作用
5. onMounted/onUnmounted:生命周期钩子(在Hook内部注册,组件销毁自动清理)

场景
1 通用DOM 交互:useMouse、useClickOutside、useScroll
2 异步请求封装:useRequest
3 定时器、事件监听

栗子:

<template>
<div>
<h3>鼠标坐标Hook</h3>
<p>X:{{ x }}</p>
<p>Y:{{ y }}</p>
</div>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'

// 自定义Hook:useMouse
function useMouse() {
const x = ref(0)
const y = ref(0)

function handleMousemove(e) {
x.value = e.clientX
y.value = e.clientY
}

onMounted(() => {
window.addEventListener('mousemove', handleMousemove)
})

onUnmounted(() => {
window.removeEventListener('mousemove', handleMousemove)
})

return { x, y }
}

// 在组件中使用Hook
const { x, y } = useMouse()
</script>

Demo02

<template>
<div>
<h3>useRequest 异步请求Hook</h3>
<button @click="run">发起请求</button>
<button @click="retry" :disabled="!error">重试</button>
<p v-if="loading">加载中…</p>
<p v-if="error" style="color:red">错误:{{ error.message }}</p>
<p v-if="data">返回数据:{{ data }}</p>
</div>
</template>

<script setup>
import { ref, onUnmounted } from 'vue'

function useRequest(apiFn) {
const data = ref(null)
const loading = ref(false)
const error = ref(null)

let abortController = null

async function run() {
if (abortController) {
abortController.abort()
}
abortController = new AbortController()

loading.value = true
error.value = null
try {
const res = await apiFn(abortController.signal)
data.value = res
} catch (err) {
if (err.name !== 'AbortError') {
error.value = err
}
} finally {
loading.value = false
}
}

function retry() {
run()
}

onUnmounted(() => {
if (abortController) {
abortController.abort()
}
})

return {
data,
loading,
error,
run,
retry
}
}

// 模拟接口函数
function mockApi(signal) {
return new Promise((resolve, reject) => {
const timer = setTimeout(() => {
resolve({ name: "张三", age: 20, id: 1001 })
}, 1500)

signal.addEventListener('abort', () => {
clearTimeout(timer)
})
})
}

// 使用Hook
const { data, loading, error, run, retry } = useRequest(mockApi)
</script>

注意
1 Hook内的生命周期,归属调用它的组件;组件销毁,Hook里面的onUnmounted自动执行
2 每次组件调用useXxx()都会生成独立的状态副本(互不干扰);想要全局共享状态,需要单独抽离一份reactive/ref放到Hook外面
3 副作用(监听、定时器)一定要在onUnmounted清理,防止内存泄漏
4 尽量返回ref/toRefs,保证解构出来的值保持响应式

赞(0)
未经允许不得转载:网硕互联帮助中心 » Vue笔记(十六)--自定义Hook
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!