《Vuejs设计与实现》8.7 事件的处理
在讲完了如何区分组件之后,我们再来看看,如何区分事件,处理事件。
- 在vue2中,事件是放在
on
之下的
const vnode = {
type:'button',
on:{
click(){}
}
}
- 在vue3中,事件则同样被扁平化,我们约定以
on
开头的都是事件,因此结构就变成了
const vnode = {
type:'button',
onClick(){}
}
这样处理的原因也是能够更方便检测,减少层级,减少递归。
那么我们怎么样把事件绑定到DOM上呢,绝大多数人第一反应肯定是addEventListener
,肯定是没问题的,而且性能也不错,是一个普适性比较高的方案,但其实,这里还是有很多优化的空间的。
假设我们就直接使用addEventListener
,当vnode
变化或者绑定的事件变化时,我们肯定需要先解绑事件,因此我们要调用removeEventListener
,如果组件变化更新比较频繁,比如列表的时候,我们不停的滑动,不停的加载列表项,频繁绑定解绑事件也会造成卡顿。
解决的办法就是我们不解绑事件,我们通过响应式变量去处理,我们可以在vnode下声明一个ref
,然后当绑定的事件变化时,动态改变它的value。我们假设,当props
变化时,会调用patchProps
,这个方法应该属于patch
我们可以在声明一个handler的匿名函数,这样我们只需要绑定一次就可以实现事件切换,因为我们每次改变的只是invoker.value
即可。
const invoker = ref(null)
const handler = (evt)=>{
if(unref(invoker)){
invoker.value(evt)
}
}
假设我们的事件现在解绑了,我们也只需要把invoker.value = null
,这样哪怕事件还在,也不会触发事件处理函数。当然,上面只是一个伪代码,真正在使用的时候,我们还需要注意
- 根据事件名缓存事件处理函数,也就是可能会有多个
invoker
,如果你只赋值一个,就会被覆盖。 addEventListener
其实是可以当定多个事件的,比如绑定2个click
事件,我觉得可以把const invoker = ref(new Set())
这样去解决,但不知道vue3是不是这样做的
转载自:https://juejin.cn/post/7137276408975327263