const useEventListener = (...args:any[])=>{
let target:HTMLElement | undefined |null | Window
let events:string[] |string
let listeners:any
let options : EventListenerOptions | undefined
// 清除监听
const cleanFns = []
if(typeof args[0] === 'string' || Array.isArray(args[0])){
[events,listeners,options] = args
target = window
}else{
[target,events,listeners,options] = args
}
if(typeof events === 'string'){
events = [events]
}
if(!Array.isArray(listeners)){
listeners = [listeners]
}
//注册
const register = (el:any,event:string,listener:any,options:any)=>{
console.log(el)
el?.addEventListener(event,listener,options)
//retur清除
return ()=> el?.removeEventListener(event,listener,options)
}
//清除
const clear = ()=>{
cleanFns.forEach((fn)=>{
fn()
})
cleanFns.length = 0
}
//监听
//如果想在侦听器回调中能访问被 Vue 更新之后的DOM,你需要指明 flush: 'post' 选项
const stopWatch = watch([target,options],([el,options])=>{
//清楚重新监听
console.log(unref(target),el)
clear()
if(!el) return;
const cloneOptions = isObject(options) ? {...options} : options
//flatMap将数组拉平
const data = events.flatMap((e)=>{
return listeners.map((l:any)=>{
return register(el,e,l,cloneOptions)
})
})
cleanFns.push(...data)
},
{ immediate: true, flush: 'post' },
)
const stop = ()=>{
stopWatch();
clear()
}
//onScopeDispose
//在当前活跃的 effect 作用域上注册一个处理回调函数。当相关的 effect 作用域停止时会调用这个回调函数。
// 这个方法可以作为可复用的组合式函数中 onUnmounted 的替代品,它并不与组件耦合,因为每一个 Vue 组件的 setup() 函数也是在一个 effect 作用域中调用的。
//getCurrentScope API 允许开发者获取当前正在执行的作用域
if (getCurrentScope()) {
onScopeDispose(stop)
}
return stop
}
vue3实现事件监听的hook
于 2024-08-02 10:48:00 首次发布