在vue中實現一個hook,在mounted添加事件監聽,頁面銷毀時移除。
默認函數有四個參數[target, type, listener, options]
target是EventTarget,作為注冊監聽器的容器,默認是window
后三個參數是addEventListener的參數
export function useEventListener(...args) { let target, type, listener, options if (isString(args[0])) { [type, listener, options] = args target = window } else { [target, type, listener, options] = args } }
首先判斷第一個實參是否為字符串,來決定target的值
然后定義一個clean變量賦值為空函數() => {}
然后需要使用watch,用之前我們需要知道watch方法返回的一個unwatch方法。
const stopWatch = watch( () => unref(target), (el) => { console.log('監聽觸發'); cleanup() if (!el) return el.addEventListener(type, listener, options) cleanup = () => { el.removeEventListener(type, listener, options) cleanup = noop } }, { immediate: true, flush: 'post' } )
給偵聽源加上unref方法,這樣可以給ref的虛擬dom添加監聽。
設置immediate為true,來立即執行。
import { watch, unref, onScopeDispose } from 'vue'
export function useEventListener(...args) {
let target, type, listener, options
if (isString(args[0])) {
[type, listener, options] = args
target = window
} else {
[target, type, listener, options] = args
}
if (!target) return noop
let cleanup = noop
const stopWatch = watch(
() => unref(target),
(el) => {
console.log('監聽觸發');
cleanup()
if (!el) return
el.addEventListener(type, listener, options)
cleanup = () => {
el.removeEventListener(type, listener, options)
cleanup = noop
}
},
{ immediate: true, flush: 'post' }
)
const stop = () => {
stopWatch()
cleanup()
}
onScopeDispose(stop)
return stop
}
function isString(str) {
return typeof str === 'string'
}
const noop = () => {}
onScopeDispose
在當前活躍的 effect 作用域上注冊一個處理回調。該回調會在相關的 effect 作用域結束之后被調用。
該方法在復用組合式函數時可用作 onUmounted 的非組件耦合替代品,因為每個 Vue 組件的 setup() 函數也同樣在 effect 作用域內被調用。
