VUE2/3源码对事件绑定的巧妙处理
简介
传统的给dom更改绑定事件处理函数,通常都是先remove,再add,而在我最近看Vue源码之后,发现Vue当中对事件绑定的处理非常巧妙。废话不多说,直接上代码。
源码处理流程对比
vue2
首先在vue2源码当中找出对应的处理函数
updateDOMListeners 这个函数当中,首先对事件们做了normalizeEvents标准化处理,然后放到updateListeners里面做更新绑定逻辑的处理
updateListeners
normalizeEvent 首先在normalizeEvent,通过cached函数对event的一些信息(事件名称对应的)做了闭包缓存处理
顺便一提cached工厂函数 cached 工厂函数,接受类型为 【入参string,返回泛形R的函数】作为参数,返回另一个 【入参string,返回泛形R的函数】 可以看到在这里会对目前的vm的事件处理函数用createFnInvoker进行包裹 createFnInvoker
原本的函数就被套用上一层invoker函数,被放到fns属性当中去执行 最后通过add函数去绑定
add
remove
解除的时候,通过removeEventListener进行解绑
在更新绑定事件函数的时候,回到updateListeners,是直接对invoker函数的fns指向进行修改,因此无需重新addEvnetListener进行换绑。达到了优化效果
vue3
vue3当中的入口就是createApp
在patchProps当中的patchEvent环节
patchEvent
createInvoker
这里是重点了,可以看到相对于vue2的invoker,vue3的invoker同样是一个函数,同样的是vue3是直接修改的invoker的value,vue2是修改的fns,其实本质上是一样的,这样造成的结果是:之前绑定的事件处理函数invoker却并没有发生改变!
addEventListener
removeEventListener
小测试
通过模拟vue和传统做法,进行1000000 -1 次事件更新,比较最后的运行时间.
<template>
<button id="invoker">Vue绑定</button>
<button id="tradition">传统绑定</button>
</template>
<script>
const invokerBTN = document.getElementById('invoker')
const traditionBTN = document.getElementById('tradition')
const tryTimes = 1000000
const eventInvoker = {
'click':()=>{
console.log('clicked!');
}
}
function testTra(){
console.time('traditional event handler')
let j = 0
while(j<tryTimes){
for(i in eventInvoker){
traditionBTN.addEventListener(i,eventInvoker[i])
traditionBTN.removeEventListener(i,eventInvoker[i])
}
j
}
console.timeEnd('traditional event handler')
}
// vei = vue event invokers
const vei = {}
function testInvoke(){
console.time('vue event handler')
let j = 0
while(j<tryTimes){
for(i in eventInvoker){
let invoker = vei[i]
if(!invoker){
invoker = (e)=>{
invoker.value && invoker.value(e)
}
invoker.value = eventInvoker[i]
invokerBTN.addEventListener(i,invoker)
vei[i] = invoker
}else{
invoker.value = eventInvoker[i]
}
}
j
}
console.timeEnd('vue event handler')
}
testTra()
testInvoke()
</script>
运行结果
可以看到差别还是蛮大的
总结
Vue源码当中对事件的绑定处理,是通过原生api【addEventListener】绑定对应的invoker函数,在invoker内部执行真正的事件处理函数,并且将内部处理函数通过指针暴露出来,从而实现更新时只需更改内存指向即可。
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanfekkc
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01