既然 W3C 已经定义了标准的 DOM Level2 事件模型,为什么 Dojo 还要提供 connect 函数来注册事件处理函数呢,为何不使用 DOM Level2 的 addEventListener 函数?从前面的叙述中也看不出 connect 与 addEventListener 有明显的不同之处。确实在处理 DOM 事件上,Dojo 的 connect 与 addEventListener 无甚大的不同,但是 Dojo 的 connect 函数还可以处理用户自定义事件。这是 addEventListener 所不具备的。下面来看看怎么使用 dojo.connect 来处理用户自定义事件。
用户自定义事件是指用户指定的函数被调用时触发的“事件”,当指定函数被调用时,将促发监听函数被调用。有点类似于 AOP 的编程思想,但在 Javascript 中实现 AOP 比起面向对象的编程语言要简单得多。
清单 6
<html> <head> <script type="text/javascript" djConfig="parseOnLoad: true, isDebug: true" src="../dojo/dojo/dojo.js"></script> </head> <body> <script type="text/javascript"> function print(fName, args) { var message = "In " + fName + "; the arguments are: " dojo.forEach(args, function(args) { message += args.toString() + " "; }) ; console.log(message); } function handler1() { print("handler1", arguments); } function handler2(a1, a2) { print("handler2", [a1, a2]); } function userFunction() { print("userFunction", arguments); } dojo.connect("userFunction", null, "handler1"); dojo.connect("userFunction", null, "handler2"); userFunction(1, 2); </script> </body> </html>
运行清单 6 的例子,会在页面中的一个模拟控制台中输出:
In userFunction; the arguments are: 1 2 In handler1; the arguments are: 1 2 In handler2; the arguments are: 1 2
调用 userFunction 时,handler1 和 handler2 也被触发了。 userFunction 就像是一个事件源,它的调用像一个事件,而 handler1 和 hander2 就是事件处理函数。那么这种情况下,事件对象又在哪呢? handler1 事件处理函数没有显式的参数,通过在控制台的输出可以得知它实际上有两个参数,值分别为 1 和 2 ; handler2 有两个显式参数,值也为 1 和 2 。所以 Dojo 只是把 userFunction 的两个参数传递给了事件处理函数,不像在处理 DOM 事件时,提供一个封装好的事件对象。在本例中 userFunction 只“连接”了两个函数,很显然它还可以连接更多的事件处理函数,这些事件将按连接的先后顺序来执行。