Dojo学习--event(2): 事件指派和对象方法

继续学习Dojo的事件机制:

事件指派(Event Delegation)

NodeList 的on函数可以给一串DOM节点赋值handler事件处理函数。dojo/on也通过事件指派来实现这个功能

事件指派的意思:
不对每一个DOM元素都指定事件处理函数,而是给DOM树中尽量最高级别的元素上指定一个事件处理函数。按照事件冒泡原理,低级别的DOM元素的事件会传递到高级别DOM元素上。这个高级别的DOM元素会检查捕获到的事件,只要判断传递来的事件的属于哪个子元素,然后去做相应的子元素的处理。

事件指派的好处是
1,减少事件处理程序的数量,提升页面的性能:每个函数都是对象,都会占用内存,所以事件处理程序的数量关系到整个页面的运行性能。
2,减少对DOM元素的访问次数:每个定义的事件处理程序都会绑定到DOM元素上,也就有对DOM元素的访问。减少事件处理程序的数量,一定程度上减少对DOM元素的访问。

适合事件指派的事件:
适合采用事件指派技术的事件包括click, mousedown, mousup, keydown, keyup, keypress。虽然mouseover和mouseout事件也冒泡,但是处理它们并不容易,而且经常需要计算它们的位置。

之前的dojo版本dojox/Nodelist/delegate 会实现这个事件委托,现在依然有用。1.10版本开始,也可以用dojo/on 模块来实现相关功能,使用on函数语法:

**on(parent element, "selector:event name",handler)**

例子如下:

<div id="parentDiv">
    <button id="button1" class="clickMe">Click me</button>
    <button id="button2" class="clickMe">Click me also</button>
    <button id="button3" class="clickMe">Click me too</button>
    <button id="button4" class="clickMe">Please click me</button>
</div>
<script>
require(["dojo/on", "dojo/dom", "dojo/query", "dojo/domReady!"],
    function(on, dom){

        var myObject = {
            id: "myObject",
            onClick: function(evt){
                alert("The scope of this handler is " + this.id);
            }
        };
        var div = dom.byId("parentDiv");
        on(div, ".clickMe:click", myObject.onClick);

});
</script>

查看运行结果: 事件指派例子–运行结果
注意:1,使用中,仍然需要dojo/query模块,即使我们不会直接使用到模块功能。因为 dojo/on需要dojo/query的选择引擎去匹配dom元素而指派事件。
2,上述例子也能说明一个问题,事件指派设计中,事件处理关注并不是高级别元素(也可以称之为父级元素),虽然这个元素作为第一个参数传递到on中。事件指派的处理函数关注的是处理匹配的子元素的操作。

对象方法

dojo/on的“前任”dojo.connect, 负责方法到方法的事件链接。这个功能已经单独成一个模块:dojo/aspect.

Publish/Subscribe

之前的例子处理的情况是:已知一个对象以及已知其要做event处理。但是,如果在你不知道一个节点对象要处理什么event的时候(也许可以理这个理解:只知道这个节点要进行和某个已知对象的event操作一样,至于具体事件处理程序不知道),或者甚至不知道何时这个对象会被创建。这种情况下,你需要Dojo 的dojo/topic模块的publish与subscribe (pub/sub)。

这个框架是1.10开始引入。Pub/sub允许注册一个处理函数handler(通过subscribe) 到一个 topic,这个topic其实是事件别名的string形式。这个事件可以拥有多种资源,被多个节点使用。当这个topic被publish时handler会被调用。

pub/sub适用场景:
当你开发一个应用时,希望有个按钮去提现用户操作。我们不想重复开发,这个小功能又不值得包装成对象。

通过以下例子更深一步理解pub/sub

<button id="alertButton">Alert the user</button>
<button id="createAlert">Create another alert button</button>

<script> require(["dojo/on", "dojo/topic", "dojo/dom-construct", "dojo/dom", "dojo/domReady!"], function(on, topic, domConstruct, dom) { var alertButton = dom.byId("alertButton"), createAlert = dom.byId("createAlert"); on(alertButton, "click", function() { // When this button is clicked, // publish to the "alertUser" topic topic.publish("alertUser", "I am alerting you."); }); on(createAlert, "click", function(evt){ // Create another button var anotherButton = domConstruct.create("button", { innerHTML: "Another alert button" }, createAlert, "after"); // When the other button is clicked, // publish to the "alertUser" topic on(anotherButton, "click", function(evt){ topic.publish("alertUser", "I am also alerting you."); }); }); // Register the alerting routine with the "alertUser" topic. topic.subscribe("alertUser", function(text){ alert(text); }); }); </script>

查看运行结果:对象事件例子–运行结果

这种模式的事件写法使得事件处理与事件对象解耦,这样有一个优点:不需要创建DOM元素,就可以进行单元。若不想再保持一个主题,topic.subscribe返回一个对象,这个对象有一个remove方法,这个方法可以移除相应事件处理(与on函数类似)。

注意: 不同于dojo.publishtopic.publish参数不需要写成数组形式。以下两种写法是相等的,注意参数的不同写法:

topic.publish("someTopic", "foo", "bar") 
dojo.publish("someTopic", ["foo", "bar"]).

Dojo事件总结

dojo事件机制很强大,也很容易使用。on方法屏蔽了浏览器之前的不一致。pub/sub框架中,dojo/topic给出了一种解绑事件处理程序与事件对象的方法。需要多花时间去熟悉这些工具,相信在web应用的构建中还是很有益处的。

相关文章
相关标签/搜索