Vue自动移除事件监听
在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 作用域内被调用。