You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository has been archived by the owner on Nov 12, 2024. It is now read-only.
先说普通事件代理,以
jQuery
为例这样其实是为
document.body
上绑定一个click
事件,当鼠标在页面上点击时,看点击的元素是否是p
元素,如果是则触发,不是则向从当前节点向上查找到符合的p
元素,一直查到body
。这里其实是有性能问题的(jQuery已经弃用的live),稍后我们再讨论并给出解决方案。事件代理其实就是把事件处理函数绑定在父级,通过事件冒泡的特点,识别触发事件的元素是否是自已期望的元素。对,重点是这个事件冒泡
Magix
中的事件代理的过程是这样的:把相应的事件绑定在父节点后,当事件发生在父节点里,父节点的事件处理函数被调用后,从触发事件的节点(target
)开始,判断节点是否有mx-eventType
属性,如果有则停下来调用相应view
的事件处理函数,如果没有则向上查找,直到父节点再来看
Magix1.0
之前的事件代理方案当前
view
使用的事件都统一绑定到vframe
根节点上,而vframe
又可以嵌套,比如嵌套后的结构如下:我们的事件是绑定在
vframe
上的,当vframe2
与vframe1
绑定相同类型的事件时,比如click
,而vframe2
的view
与vframe1
的view
具有相同的事件处理函数时,比如selectAll
,那么问题就来了:鼠标点击在vframe2
的SelectAll checkbox上时,vframe2
先处理,而同时事件冒泡,冒泡到vframe1
上时,vframe1
的selectAll
方法同样会被触发。这里因为
vframe1
节点与vframe2
节点都绑定了click
事件,而由于事件冒泡的原因,同时事件类型及方法名又一致,当点击在vframe2
内部时,vframe2
处理完事件向上冒泡到vframe1
,导致vframe1
又处理了一遍,那或许你会说为什么不取消事件冒泡呢?因为在我们的项目中,我们有可能引入其它组件,比如弹出日历等,需要鼠标点击在页面其它位置时日历需要隐藏消失。所以我们不能直接就把事件冒泡取消,否则日历也无法隐藏(像日历这种通常是绑定在
document
,需要相关事件冒泡到document
)问题出来了总得有个解决办法
第1个解决方案:
明确事件的处理
vframe
,类似上图,当鼠标点击在vframe2
时,当vframe2
处理完事件后,给打一个标记,标明当前事件是被处理过的,当vframe1
收到后,先判断是否是处理过的,如果是处理过则不再理会说到这里,大家可以想象一下,如果嵌套的
vframe
比较多时,鼠标点击在最内部的vframe
时,由于事件冒泡,冒泡到每一层的vframe
时,这一层的vframe
都需要对事件做一次判断,而这些判断其实是不必要的,因为事件已经被内部vframe
处理了,为什么还在再次判断?这地方多少会有些性能损耗第2个解决方案:
把代理节点提高到
body
上,如果事件代理在body
上而不是vframe
上,把注册在vframe
上相同的监听统一合并到body
上,这样vframe
节点不需要注册任何事件,对于嵌套的vframe
,也是统一在body
上处理事件,不需要每一层vframe
的判断了。该方案所有事件在绑定时,不管什么事件类型都绑定的是同一个事件处理函数,在这个事件处理函数内部再决定调用哪一个view的处理函数。内部针对magix的特点,对事件这块再特殊优化,从而提升性能,原理接下来讨论
回到开头我们的那个问题(jQuery live):事件是绑定在
body
上的,每当事件发生时,我们都要从发生事件的节点向上查找带有mx-eventType
标识的节点,直到body
。那我们来看一种情况:假设html结构是这样的:
document.body
注册了一个click
事件,当鼠标点击在button
上时,target
即符合我们的要求(带有mx-click
属性),所以不再向上查找,把button
转交给相应的vframe
去处理,而如果点击在button
外部时,由于div
不带mx-click
属性,则会一直向上查找,直到body
,而如果这种嵌套比较深的话,每次点击在button
外部时,都需要从里至外的查找到body
,性能上肯定不乐观,如何提升这块的性能 ?我们发现不管是点击在
div2
内部还是div1
内部,从事件触发的节点到body
这条路径上是没有带mx-eventType
属性的节点的,所以在向上查找的过程中,会把整条路径上的节点都记录下来,如果到body
还未找到带mx-eventType
的节点,则会把这些节点都标记上不需要处理click
事件。表明从这个节点向上是没有带
mx-eventType
属性的节点的,当下次再点击时,首先看当前这个节点是否已经被标识,如果被标识没有eventType
类型的事件,则不再向上查找由于Maigx事件本身是代理进行的,直接在期望的节点上写
mx-event
即可,最好不要出现类似这样的代码:直接在
li
上面写mx-click
即可,如果是在ul
节点上,Magix本身需要从事件触发的节点向上找到带mx-eventType
,开发者还需要从target
再来判断一次事件触发节点是否是期望的li
,从而拉低了性能。经过上述方案后,对于高频事件比如
mousemove
也能很好的应对,不至于鼠标在页面内快速移动而造成CPU
瞬间上升The text was updated successfully, but these errors were encountered: