在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 作用域內被調用。