dojo 的Events

这节 我们将学习dojo/on ,dojo是如何让连接dom 事件变得简单的,我们也会探索dojo 的订阅/发布 框架dojo/topic.

你的太多的javascript 代码是为事件而准备的,响应或者生成新的事件。这将意味着创建快速反映和交互的web应用的关键就是创建高效的事件连接。

事件连接允许你的应用响应用户的交互 等待动作事件的发生,dojo 的主要的dom 事件处理机制是dojo/on,我们来学习此模块。

你也许会问Dom是否已经提供了一个事件处理机制,去注册事件处理者,是的的确提供了,但不是所有的浏览器都遵循dom标准。

在主流的浏览器中对事件的处理有三种方式(addEventListener, attachEvent, and DOM0)

在一个浏览器中使用两个不同的事件对象会将注册的方法的处理器置于随机的顺序而引起内存泄露,你将会面临一个灾难。

幸运的是他们将解决不同DOM api 差异性和防止内存泄露放在了一个API 里面:dojo/on我们来看下面的标记:

 

<button id="myButton">Click me!</button>
<div id="myDiv">Hover over me!</div>

设想一下当你按下按钮时,你想要div 的颜色变成 蓝色的,当你离开的时候想要变成红色的。

当你移上鼠标时变成白色 dojo/on 实现起来非常的简单。

 

require(["dojo/on", "dojo/dom-style", "dojo/mouse", "dojo/domReady!"],
    function(on, domStyle, mouse) {
        var myButton = document.getElementById("myButton"),
            myDiv = document.getElementById("myDiv");
         
        on(myButton, "click", function(evt){
            domStyle.set(myDiv, "backgroundColor", "blue");
        });
        on(myDiv, mouse.enter, function(evt){
            domStyle.set(myDiv, "backgroundColor", "red");
        });
        on(myDiv, mouse.leave, function(evt){
            domStyle.set(myDiv, "backgroundColor", "");
        });
});

注意:

dojo/mouse 同样需要

dojo/on 不是原生的支持mouseentermouseleave事件,dojo/mouse添加了这样的支持。

这个例阐述了一般的模式on(element, event name,handler)还可以使用令有一个模式:在当前元素上加一个事件,连接的处理器。

这种模式适用于所有的window,document, node, form, mouse, and keyboard 事件。

On 方法不但规范了注册事件的API,而且规范化了事件处理器是如何被调用的。

1.   事件处理器按照注册的顺序来调用,

2. 他们总是把一个事件对象当作他们的第一个参数。

3. 事件对象拥有一个.target(目标)属性一个stopPropagation(阻止传播)方法和一个preventDefault(阻止默认值)方法

就像DOM的API Dojo 提供一个方法删除事件处理器。handle.remove on方法的返回值是一个拥有remove方法的简单对象,调用此方法将删除事件监听。例如你想要一个只执行一次 的方法你可以按照下面做。

var handle = on(myButton, "click", function(evt){
    // Remove this event using the handle
    handle.remove();
 
    // Do other stuff here that you only want to happen one time
    alert("This alert will only happen one time.");
});

顺便说一下:

dojo/on包含了一个便利的方法处理这些一次性的事件on.once.他接收和on一样的参数。

一旦结束解除将删除事件处理器。

最后一点要记住的是:on 将执行在第一个参数传入的节点环境的事件处理器。

一个例外是:当on 使用委派事件。

然而你可以使用lang.hitch(在dojo/_base/lang模块中)指定运行处理器的上下文。

使用对象方法时Hitching是非常的有用的。

 

require(["dojo/on", "dojo/_base/lang", "dojo/domReady!"],
    function(on, lang) {
         
        var myScopedButton1 = document.getElementById("myScopedButton1"),
            myScopedButton2 = document.getElementById("myScopedButton2"),
            myObject = {
                id: "myObject",
                onClick: function(evt){
                    alert("The scope of this handler is " + this.id);
                }
            };
         
        // This will alert "myScopedButton1"
        on(myScopedButton1, "click", myObject.onClick);
        // This will alert "myObject" rather than "myScopedButton2"
        on(myScopedButton2, "click", lang.hitch(myObject, "onClick"));
         
});

节点列表事件

节点列表提供了一个方法注册事件到多个节点。

On 方法 ,此方法使用了同dojo/on不使用第一个参数一样的格式(因为在节点列表中的节点就是你要连接事件的节点)

On方法包含了dojo/query所以你不需要明确的指定dojo/on(当使用NodeList.on.)的时候。

来看一个更高级一点的例子。

 

注意:

NodeList.on返回一个存放 on 事件处理器的一个数组。这些处理器可以在以后删除。

数组也包含一个便利的顶级删除方法,一次性上拿出所有的事件监听器。

事件委托

如上所述,节点列表的On 方法使得将相同的处理器勾连到多个Dom的相同的事件上。

dojo/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/query","dojo/domReady!"],

    function(on){

         

        varmyObject = {

            id:"myObject",

            onClick:function(evt){

                alert("Thescope of this handler is " + this.id);

            }

        };

        var div =document.getElementById("parentDiv");

        on(div,".clickMe:click", myObject.onClick);

         

});

</script>

 

注意: 虽然我们不直接的使用dojo/query,但此模块仍然是需要的。

这是因为:dojo/on 需要一个 dojo/query 暴露的选择器引擎用来匹配事件委托所使用的选择器。

他没有被自动的加在dojo/on 用来减少他出现的次数,避免为了一个不经常使用的特性而增加开发者的负担。

 

运行上面的展示例子注意 this 依然指向我们真正感兴趣的节点。

而不是 parentDiv 节点,当使用委托时一个重要的区别:this不再指向传入的第一个参数的节点,而是指向匹配选择器的节点。

一旦你想要知道他时,这确实是非常有用的。

 

Publish/Subscribe(发布/订阅)

在此之前,以上的所有例子都使用一个已存在的对象作为事件的发生器(你注册的等待事件的发生)。

如果你没有一个节点的引用,或者并不知道对象是否已经创建。这就是dojo 的发布/订阅框架引入的原因。

过 dojo/topic模块,Pub/sub允许你为一个主题注册一个处理器,(主题是一个事件的别名,此事件是多源的,以字符串形式描述)当配发布的时候主题将被调用。

我们设想一下,在我们开发的应用中,我们需要一些按钮,来弹出动作的用户,我们想要一次性的将弹出写完,我们也不想创建一个包装对象,同过按钮来注册此小程序,Pub/sub能够应用在此场景中。

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

require(["dojo/on", "dojo/topic", "dojo/dom-construct", "dojo/domReady!"],
    function(on, topic, domConstruct) {
         
        var alertButton = document.getElementById("alertButton"),
            createAlert = document.getElementById("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 方法的对象,能够删除各自的处理器。

 

注意:不像 dojo.publish, topic.publish不期望传入的发布参数放在数组中,例如

topic.publish("someTopic","foo", "bar")和dojo.publish("someTopic",["foo", "bar"])是等价的。

总结:

Dojo的事件系统是相当的强大、非常的易用。On 方法解决了dom 事件的跨浏览器问题。Dojo 的pub/sub 框架,dojo/topic

让开发者能够容易的将事件处理器与事件发生器解耦,花费一些时间来熟悉这些工具,他们将会是你创建你web应用的宝贵财富。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值