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 作用域内被调用。

posted @ 2022-02-01 20:11  Bob康康  阅读(2180)  评论(0编辑  收藏  举报