订阅者被成功注册到事件分发器后,事件分发器需要根据相应到的事件进行分发,本节课将重点讲述如何进行事件分发。


教学视频


课程笔记


事件的触发

事件的触发通过函数dispatchEvent或者dispatchCustomEvent来触发。dispatchCustomEvent会自动创建一个CustomEvent;也可以先创建一个CustomEvent的event,然后通过dispatchEvent的方法来触发。


事件的分发

在dispatchEvent的函数中,主要是实现了listenerID对应订阅者的排序,按照顺序调用订阅者的回调函数,最后再将状态更新。


在对listenerID对应订阅者排序的时候,先将优先级list从小到大排列,并找到第一个优先级大于0的订阅者索引,然后将Node对应的订阅者list按照绘制顺序进行排序。并且如果经常排序会导致性能问题,EventDispather采用做标记的办法,在变动做标记的listenerID的时候,就会重新排序,否则就不进行重新排序。在如下函数中会做标记:setLocalZOrder、setGlobalZOrder、setPriority、forceAddEventListener、removeEventListener。如果关联Node或者关联Node的父类Node发生Z变换,就会需要重新排序。


事件允许嵌套,即事件的回调函数中dispatchEvent另外一个事件。在函数中通过DispatchGuard guard(_inDispatch);标记,_inDispatch初始为0,dispatch的时候+1,生命周期结束的时候-1。需要注意的是:嵌套事件中不能执行一个相同的事件,否则会导致死循环。


在事件分发的过程中,优先级高的订阅者可以通过event的stopPropagation选择让事件停止传播


订阅者的修改

在事件分发的过程中修改订阅者的优先级,会在下一次触发事件的时候生效,而通过setEnable、setPause、setRegistered会即时生效。

在事件分发的过程中,订阅者的删除,只是将其标记为setRegistered(false),而在分发结束的时候移除。

在事件分发的过程中,订阅者的添加,只是加入临时数组_toAddedListeners,在所有事件分发结束后将其加入订阅者list。


事件与Node

调用Node的onExit的时候会调用Node及其子Node的pause函数,在pause函数中,会调用pauseEventListenersForTarget方法,调用OnEnter会调用Node及其子Node的resume函数,在resume函数中,会调用resumeEventListenersForTarget方法。

删除Node会自动移除和Node相关的订阅者。