一般在组件中使用addeventlistener添加事件监听的时候,在组件销毁的时候都要使用removeEventListener进行销毁,不然会造成内存泄漏。

但是addeventlistener和removeEventListener的参数必须是一样的,才有效

例如:在vue3中添加全局自定义指令

app.directive('copy', {
  mounted(el, binding, vnode, prevVnode) {
    el.addEventListener('click', (e) => {
      console.log(e, el, binding, vnode, prevVnode)
    })
  },
  beforeUnmount(el, binding, vnode, prevVnode) {
    el.removeEventListener('click', (e) => {
      console.log(e, el, binding, vnode, prevVnode)
    })
  }
})

上面我们在自定义指令的时候在mounted中对dom添加事件监听,在beforeUnmount中进行事件解绑,但是第二个参数是匿名函数,所以add和remove的函数不是同一个所以参数不一致,remove是无效的

当我们修改成参数一致时:

const clickHandle = function(e) {
  console.log(e)
}
app.directive('copy', {
  mounted(el, binding, vnode, prevVnode) {
    el.addEventListener('click', clickHandle)
  },
  beforeUnmount(el, binding, vnode, prevVnode) {
    el.removeEventListener('click', clickHandle)
  }
})

上面这样写确实可以消除掉绑定的事件,但是无法进行参数的传递无法再函数中使用el,biinding等参数

所以我们需要这样写:

const getEventHandle = function (data){
  const fn = (e) => {
    if (!e._kpma_vts) {
      e._kpma_vts= Date.now()
    } else if (e._kpma_vts<= fn.attached) {
      return
    }
    e.stopPropagation()
    e.preventDefault()
    fn.callBack(e)
  }
  fn.attached = Date.now()
  Object.assign(fn, data)
  return fn
}
const clickHandle = function(e){
  console.log(e)
  const {el, binding, vnode, prevVnode} = this
  console.log(el, binding, vnode, prevVnode)
}
app.directive('copy', {
  mounted(el, binding, vnode, prevVnode) {
    el._kpma_event = getEventHandle({el, binding, vnode, prevVnode, callBack: clickHandle})
    el.addEventListener('click', el._kpma_event)
  },
  beforeUnmount(el) {
    el.removeEventListener('click', el._kpma_event)
  }
})

Logo

前往低代码交流专区

更多推荐