VueUse 基于 Vue 组合式 API 的实用函数库,提供了一组高效且易用的组合式 API,用于简化 Vue 3 开发中的常见需求。
本文我们来看下 createEventHook 这个函数的实现 猛击访问文档 主要函数仅不到 30 行,它是一个用于创建事件钩子的函数,单看这段话其实很难理解它是用来干什么的!
先来看一下官方的示例
逻辑封装
import { createEventHook } from '@vueuse/core'
export function useMyFetch(url) {
const fetchResult = createEventHook<Response>()
const fetchError = createEventHook<any>()
fetch(url)
.then(result => fetchResult.trigger(result))
.catch(error => fetchError.trigger(error.message))
return {
onResult: fetchResult.on,
onError: fetchError.on,
}
}
使用
<script setup lang="ts">
import { useMyFetch } from './my-fetch-function'
const { onResult, onError } = useMyFetch('my api url')
onResult((result) => {
console.log(result)
})
onError((error) => {
console.error(error)
})
</script>
这段逻辑是对请求做了一层封装返回 onResult、onError 函数,当请求成功触发 onResult 、失败时触发 onError 函数,相当于是执行了对应的回调函数
当然你会说直接返回 Promise 不就行了吗?这只是一个 🌰 告诉你它能做什么!
即可以将原有需要在组合式函数传入的回调函数直接暴露出去!
看下源码
export function createEventHook<T = any>(): EventHook<T> {
// 存储注册的的方法
const fns: Set<Callback<T>> = new Set()
// 移除注册的方法
const off = (fn: Callback<T>) => {
fns.delete(fn)
}
// 注册方法
const on = (fn: Callback<T>) => {
fns.add(fn)
const offFn = () => off(fn)
tryOnScopeDispose(offFn)
return {
off: offFn,
}
}
// 触发所有注册的方法
const trigger: EventHookTrigger<T> = (...args) => {
return Promise.all(Array.from(fns).map(fn => fn(...(args as [T, ...unknown[]]))))
}
return {
on,
off,
trigger,
}
}
首先看到返回了三个函数 on(注册方法)、off(移除注册的方法)、trigger(触发所有注册的方法)
存储注册的的方法
const fns: Set<Callback<T>> = new Set() 使用 Set 来存储绑定的方法
Set对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用 猛击直达 mdn。
delete移除Set中与这个值相等的元素,返回一个布尔值。
add在Set对象尾部添加一个元素。返回该Set对象。
移除注册的方法
方法是通过 Set 存储的,需要传入绑定的函数进行删除
const off = (fn: Callback<T>) => {
fns.delete(fn)
}
注册方法
查看 on 函数的实现,可以理解为何使用 Set 来存储绑定的方法。on 函数允许绑定多个方法,而 Set 的特性能够确保同一个方法即使多次绑定,也只会触发一次。此外,on 函数返回一个 off 方法,用于移除已注册的方法。
大家可能注意到 on 函数里调用了一个 tryOnScopeDispose 他是用来干什么的呢?
先来看下它的实现
import type { Fn } from '../utils'
import { getCurrentScope, onScopeDispose } from 'vue-demi'
/**
* Call onScopeDispose() if it's inside an effect scope lifecycle, if not, do nothing
*
* @param fn
*/
export function tryOnScopeDispose(fn: Fn) {
if (getCurrentScope()) {
onScopeDispose(fn)
return true
}
return false
}
看起来是根据 getCurrentScope 的值决定是否执行 onScopeDispose 让我们看下官方文档对这两个方法的解释!
到这里 tryOnScopeDispose 的作用也就显而易见了 在当前的 Vue 响应式作用域中注册一个清理函数。如果不在作用域内,则什么也不做。
在 on 方法里调用是传递了 offFn 函数,所以在 on 方法里调用 tryOnScopeDispose 的作用是:在当前作用域卸载时移除注册的方法!
触发所有注册的方法
trigger 方法会触发所有已绑定的方法,使用 Array.from 将 Set 类型的数据转换成数组然后使用 Promise.all 执行所有方法。
总结
本文讲解了 vueuse 中 createEventHook、tryOnScopeDispose 两个工具函数的作用以及实现!
其中 createEventHook 虽然只有不到 30 行代码但实现思路仍值得我们学习!