3.5 队伍应该这样带——小工具之间的消息机制
对于灵活网页布局使用的 Fusion 这个复杂的浏览器内框架来说,有一套简单易用的事件机制是极为重要的。很不幸的是 Javascript 语言本身并没有事件系统,那么,各个框架只能自己实现这样的一套事件机制。
其实这样的问题, OpenLayers 也遇到了。因此 OpenLayers 自己实现了一套这样的事件机制。但是, OpenLayers 的事件机制存在着一些缺陷,因此, Fusion 自己又实现了一套这样的事件机制。也就是说,在 Fusion 内部,其实存在着两套事件机制:一套是 OpenLayers 实现的,在 Fusion 中主要用于同 OpenLayers 打交道。而另外一套则是 Fusion 实现的, Fusion 中的平台与小工具彼此之间靠的就是这一套事件机制。两套机制都能够起到事件的作用,在您编写小工具的时候可以采用任何一套。
这里我们将从事件的定义、注册、触发等方面分别讲解这两套机制,并比较这两套机制的不同。
3.5.1 必选组件—— Fusion 的事件机制
在 Fusion 里,如果你想让一个类具有事件机制,只要让这个类继承自 Fusion.Lib.EventMgr 就可以了。常见的用于注册、触发事件的函数都编写在类 Fusion.Lib.EventMgr 中。当您的类继承自这个类,您的类也就自动拥有了这些函数。
Fusion 认为,所以组件都是需要事件机制的。因此, Fusion 在所有组件内都内置了事件机制。具体表现为, Fusion.Widget 这个小工具的基类是继承自 Fusion.Lib.EventMgr 的。因此,当您编写小工具时,您就不必费神考虑如何让小工具具有事件机制了。
那么,事件发出方如何声明一个自己的事件呢?
首先,如果如果这个事件是自己创建的,不是使用的已有事件类型,我们要创建一个唯一的该事件类型的标识。 Fusion 的事件类型是用一个 int 值标识的。为了保证每一个事件类型的标识值各不相同, Fusion 内置了一个变量,叫做 Fusion.Event.lastEventId 。该变量记录了当前最后一个没有被使用的事件类型标识值。当您想要获得一个事件类型标识的时候,只需要获取该变量的值即可,当然也不要忘了将该变量值进行增加以供下一个来获取事件类型标识的人使用。 Fusion 推荐的声明事件类型的格式如下面所示:
Fusion.Event. 事件类型名称 = Fusion.Event.lastEventId++;
这里事件类型名称的字母一般全部采用大写字母,并在单词和单词间用下划线分隔。这样,“ Fusion.Event. 事件类型名称”这个变量中就保存了这个事件类型的标识。将来声明、注册和触发事件的时候,都需要这个标识。
需要注意的是,这个获取标识的代码是直接写在 Javascript 全局的脚本中的,而不是在写在任何一个类的代码里面。
现在,我们已经有了一个事件类型的标识。接下来,事件发出方需要声明它具有该事件。声明事件的方法是:
this.registerEventID(Fusion.Event. 事件类型名称 );
这里,我们不难看出, Fusion 的事件机制是不支持在同一个类型内声明两个相同类型的事件的。如果想要声明两个事件,就必须使用不同的事件类型。这也正是 Fusion 事件机制的不足。
现在,事件发出方已经完整的声明了一个事件。接下来,它只需要在合适的时候触发事件即可。触发事件的方法是:
this.triggerEvent(Fusion.Event. 事件类型名称 , 其他参数 );
这里您可能有些疑惑,这个“其他参数”是什么呢? Fusion 的事件并没有严格限定传递内容的格式。因此,事件的发出方可以在触发事件的时候任意选择传递的参数,您只要保证每次传递的参数内容都相同就可以了。
至此,事件发出方已经做好了它需要的工作。那么,事件接收方又该如何监听这个事件呢?
首先,要定义一个事件的处理函数,这个函数的参数列表与事件发出方的 triggerEvent 传入的参数必须符合。可是因为 Fusion 框架并没有限定传递内容的格式。那么,接收方该如何知道参数列表的内容呢?答案是:双方口头(文档)约定。这一点确实有点让人恼火,如果发出方没有编写好自己的文档,那么接收方肯定是一头雾水。但是没有办法,因为 Javascript 是一个弱类型的语言,变量的类型可以是任意的,也可以在运行时任意增减成员内容。所以,暂时也只能通过文档来约定了。
下一步,就是将该处理函数注册到发出方的该事件中。注册处理函数的方法是:
事件发出方 . registerForEvent(Fusion.Event. 事件类型名称 , 处理函数 );
这样,当事件发出方触发一个事件的时候,它就会依次调用所有注册了该事件的处理函数。