原题:Events with Dojo
原文链接: http://dojotoolkit.org/documentation/tutorials/1.6/events/
作者: Bran Forbes
译者: wangqiang

本文将与读者一同深入探究dojo.connect,如何使用Dojo来轻松的绑定DOM事件以及在原生对象上自定义事件。同时我们也将对Dojo的publish/subscribe框架进行探讨。

难度:初学者
适用Dojo版本:1.6

前言

很多的JavaScript代码都是围绕着事件的,包括创建新事件或是对事件的响应。这意味着建立一个交互式的网络应用的关键就是创建有效的事件连接体制。事件连接体制支持你的应用程序建立与用户的互动及等待接受用户的操作。在浏览器环境下具有原生的DOM事件,但同时我们也希望函数也可以具有类似这些事件一样的调用方式:“当某件事发生时,调用此函数。”dojo.connect——Dojo事件体制中一个主要方法就提供了这一功能。

DOM事件

你可以会提出疑问:“DOM不是已经提供了为事件注册处理函数的机制了吗?”的确如此,但并非所有浏览器都提供对DOM规范的全面支持,纵观主流浏览器的DOM实现机制,共有三种方式来实现对事件处理函数的注册机制(addEventListener, attachEvent,以及DOM0)。另外还有两种其他的事件实现机制和一个浏览器采用“随机顺序”对处理函数进行注册,并在注册事件处理器时会导致内存泄露,这对用户的应用角度来说也是一个潜在的灾难性因素。

幸好,Dojo为用户提供了统一的DOM事件机制,通过使用Dojo的dojo.connectAPI,用户可以避免各种DOM API的分歧,同时DOJO也预防了内存泄露问题。
假设我们有如下一段页面代码:

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

这里假设我们希望在点击按钮时使div变为蓝色,而当鼠标悬浮在其上时变为红色,移出时变回白色。下面的代码示例让我们看到使用dojo.connect可以很容易做到这些:

var myButton = dojo.byId("myButton"), myDiv = dojo.byId("myDiv"); dojo.connect(myButton, "onclick", function(evt){ dojo.style(myDiv, "backgroundColor", "blue"); }); dojo.connect(myDiv, "onmouseenter", function(evt){ dojo.style(myDiv, "backgroundColor", "red"); }); dojo.connect(myDiv, "onmouseleave", function(evt){ dojo.style(myDiv, "backgroundColor", ""); });

通过上面的例子我们得出dojo.connect的一般用法:dojo.connect(element, event name, handler)。这一用法可用于所有的窗口(window), 文档(document), 节点(node), 表单(form),鼠标以及键盘事件上。注意,在这个例子中,所有的事件名都采用了小写,虽然这并非强制性的,而且Dojo会针对不同浏览器对这一参数进行格式化,可对事件名称采用一致的格式化是一个较好的编码习惯。
dojo.connect方法不仅是一个时间注册API,同时它也可以定义如何对事件处理器进行调用:

  • 事件处理器总是按其注册顺序进行调用
  • 当事件处理器被调用时,第一个参数始终为一个事件对象
  • 事件对象将会有一个 “target”属性,一个"stopPropagation"方法,和一个“preventDefault”方法

如同DOM API一样,Dojo提供了如何对事件处理器进行注销(解除连接)的方法:dojo.disconnect。将dojo.connect方法的返回值作为参数传递给dojo.disconnect即可解除该事件处理器与事件之间的连接。例如,如果你想定义一个只运行一次的事件处理器,可以如下例所示进行定义:

var handle = dojo.connect(myButton, "onclick", function(evt){ // Disconnect this event using the handle dojo.disconnect(handle); // Do other stuff here that you only want to happen one time alert("This alert will only happen one time."); });

最后一项需要注意的是:dojo.connect方法可在handler参数前定义一个可选参数,该参数用于定义handler的上下文。如果该参数未被指定,事件处理器的默认运行上下文将被设置为所传入的第一个参数node或是window对象(这一选择依赖于浏览器)。当使用widget时,
这一参数是非常重要的。

var myScopedButton1 = dojo.byId("myScopedButton1"), myScopedButton2 = dojo.byId("myScopedButton2"), myObject = { id: "myObject", onClick: function(evt){ alert("The scope of this handler is " + this.id); } }; // This will alert "myScopedButton1" dojo.connect(myScopedButton1, "onclick", myObject.onClick); // This will alert "myObject" rather than "myScopedButton2" dojo.connect(myScopedButton2, "onclick", myObject, "onClick");

查看Demo

当scope对象参数被指定后,handler参数必须为一个scope对象中的方法的名称或者是一个函数对象,如上例中的最后一行,dojo.connect(myDiv, "onclick", myObject, myObject.onClick);。当handler参数为一个字符串时,其必须是一个大小写敏感的scope对象中的方法名,Dojo是无法对这一参数进行自动格式化的。

NodeList事件

如之前提到过的,dojo.NodeList提供了一个方法用于向多个节点注册事件。除了第一个参数外,其用法与dojo.connect方法基本一致。首先让我们看一个例子:

<button id="button1" class="clickMe">Click me</button> <button id="button2" class="clickMeAlso">Click me also</button> <button id="button3" class="clickMe">Click me too</button> <button id="button4" class="clickMeAlso">Please click me</button> <mce:script type="text/javascript"><!-- var myObject = { id: "myObject", onClick: function(evt){ alert("The scope of this handler is " + this.id); } }; dojo.query(".clickMe").connect("onclick", myObject.onClick); dojo.query(".clickMeAlso").connect("onclick", myObject, "onClick"); // --></mce:scrip

然而,这一用法有一个缺点:我们无法注销已连接的事件处理器。dojo.NodeList.connect出于便于使用的原因,将返回一个dojo.NodeList对象以用于链式调用,而并不是返回事件处理器列表。如果你确认并不需要对你的事件处理器进行注销操作,那么可以使用该方法。

查看Demo

对象方法

前面提到过,dojo.connect是Dojo的事件处理机制的核心。该结论也同样适用于原生对象,只不过针对原生对象,你需要将其中的成员方法想象成为事件。假设在页面上有一个按钮,同时我们有一个JS对象用于显示(或隐藏)该按钮:

<button id="myButton">My button</button> <mce:script type="text/javascript"><!-- var myButtonObject = { onClick: function(evt){ alert("The button was clicked"); } }; dojo.connect(dojo.byId("myButton"), "onclick", myButtonObject, "onClick"); // --></mce:script>

这里我们希望能够有一段代码用于通知按钮何时被点击。我们可以连接myButtonObject的onClick方法而并不需要对按钮的DOM节点上再绑定事件处理器:

dojo.connect(myButtonObject, "onClick", function(evt){ alert("The button was clicked and 'onClick' was called"); });

这里需要注意的是,如果连接到的是一个原生对象,那么将无法对事件名(dojo.connect的第二个参数)进行格式化,另外,所有被传入到被连接方法的参数也将作为参数传给处理器方法:

var myButtonObject2 = { onClickHandler: function(evt){ this.onClick(evt, "another argument"); }, onClick: function(){} }; dojo.connect(dojo.byId("myButton2"), "onclick", myButtonObject2, "onClickHandler"); dojo.connect(myButtonObject2, "onClick", function(evt, another){ alert("The button was clicked, we were given a second argument: " + another); });

由于DOM节点的事件处理器方法仅仅有一个参数,即事件对象,那么其连接的事件处理器方法也仅仅会被传入这一个参数;而连接到原生对象上的处理器方法将接受与被连接方法一样的多个参数。除了以上两点不同外,对于在DOM节点和原生对象上使用dojo.connect则再没有其他的区别。

连接到原生对象方法上现在看起来好像不是特别实用,不过接下来我们就会看到这一技术在小部件(widgets)上面是非常有作用的。另外,这一技术也很适用于特效应用,在其他的tutorial中会有关于特效的深入讲解,但在这里我们可以提供一个例子:

<button id="fadeButton">Fade block out</button> <div id="fadeTarget" class="red-block"></div> <mce:script type="text/javascript"><!-- var fadeButton = dojo.byId("fadeButton"), fadeTarget = dojo.byId("fadeTarget"); dojo.connect(fadeButton, "onclick", function(evt){ var anim = dojo.fadeOut({ node: fadeTarget }); dojo.connect(anim, "onEnd", function(){ alert("The fade has finished"); }); anim.play(); }); // --></mce:script>

查看Demo

这里我们不对特效相关的内容做过多的介绍,只需要知道dojo.fadeOut将返回一个带有onEnd方法的对象,onEnd方法将在特效完成后被触发。在此,我们可以将返回对象的onEnd方法进行绑定,弹出对话框告诉用户动画特效何时结束。在这一例子里,当红色区域淡出效果结束后,我们所绑定的处理函数就将会被触发。

Publish/Subscribe

到目前为止,以上的例子都是针对已经创建的对象(DOM节点,某个小部件[widget],或是某个特效对象),将我们的事件处理器绑定在其上,并以其作为事件发布者。那么,当我们并没有将事件处理器绑定到某个对象上,或者我们不知道要绑定的对象是否已经被创建时,我们又该如何去做呢?在这种情况下,我们就会需要用到Dojo的publish和subscribe(pub/sub)框架了。pub/sub使我们可以将某个处理器注册(或称之为“订阅”[subscribe])到某个“主题”(一个具有多个事件触发源的事件的特定名称,可用字符串表示),我们所注册的处理器将在该绑定“主题”被发布时被触发调用。

假设我们正在开发某一个应用,其中需要创建一些按钮来告知用户相应的行为。我们既不想重复的写这一通知程序,也不希望通过在按钮中写入内嵌对象来实现事件注册。那么最好的方法就是使用pub/sub:<button id="alertButton">Alert the user</button> <button id="createAlert">Create another alert button</button> <mce:script type="text/javascript"><!-- var alertButton = dojo.byId("alertButton"), createAlert = dojo.byId("createAlert"); dojo.connect(alertButton, "onclick", function(evt){ // When this button is clicked, // publish to the "alertUser" topic dojo.publish("alertUser", ["I am alerting you."]); }); dojo.connect(createAlert, "onclick", function(evt){ // Create another button var anotherButton = dojo.create("button", { innerHTML: "Another alert button" }, createAlert, "after"); // When the other button is clicked, // publish to the "alertUser" topic dojo.connect(anotherButton, "onclick", function(evt){ dojo.publish("alertUser", ["I am also alerting you."]); }); }); // Register the alerting routine with the "alertUser" // topic. dojo.subscribe("alertUser", function(text){ alert(text); }); // --></mce:script>

这一事件模式的一个优点是,我们不需要创建任何的DOM对象来进行单元测试,通知程序与事件是完全解耦合的。以下是一些pub/sub的一些注意事项:

  • dojo.subscribe的调用方式与dojo.connect的调用方式相类似(dojo.subscribe(topic, handler)或dojo.subscribe(topic, scope, handler or method name))
  • dojo.publish方法的第二个参数必须是一个数组对象,该数组对象中的元素即为主题处理器函数的参数。
  • dojo.sbuscribe将返回一个对象,该对象可被传入到dojo.unsubscribe方法用于注销该主题中的特定的处理器(作用与dojo.connect及dojo.disconnect相似)

小结

Dojo的事件系统十分强大,同时也十分易于使用。dojo.connect方法可以使用户忽略DOM对象与原生对象的事件的区别,以及事件在不同浏览器的不一致。Dojo的pub/sub则提供给开发人员一种很方便的解耦合事件处理器与事件发布者的方法。一旦你对这些工具有所了解,它们将成为你开发Web应用中的一项利器。

Dojo 1.6 官方教程:Dojo中的事件相关推荐

  1. java 中鼠标事件_[Java教程]js中鼠标事件总结

    [Java教程]js中鼠标事件总结 0 2017-07-11 00:00:19 js中鼠标事件主要有onclick,onmousedown,onmouseup,oncontextmenu,ondblc ...

  2. Dojo 1.6 最新官方教程: Dojo DOM 函数

    本文翻译自: Dojo DOM Functions 原作者: Sam Foster 翻译: Siqi (siqi.zhong@gmail.com) 在本教程中,您将学到如何使用Dojo简单地跨平台操作 ...

  3. PyTorch-Tutorials【pytorch官方教程中英文详解】- 1 Quickstart

    在PyTorch深度学习实践概论笔记5-课后练习2:pytorch官方教程[中英讲解]中跟着刘老师课后练习给的链接学习了pytorch官方教程,后来发现现在有更新版的教程,有时间正好也一起学习一下. ...

  4. Dojo 1.6 最新官方教程: Hello Dojo!

    Hello Dojo 作者:Sam Foster 译者:ZhuXiaoWen 原文: http://dojotoolkit.org/documentation/tutorials/1.6/hello_ ...

  5. Dojo QuickStart 快速入门教程 (2) 基本框架

    下载库 首先,下载 Dojo 库:http://www.dojotoolkit.org/downloads 放了方便测试,我将文件将解压到 Web Server 的 "js/dojotool ...

  6. Dojo mobile TweetView 系列教程之三——Tweets和Mentions视图

    Dojo mobile TweetView 系列教程之三--Tweets和Mentions视图 分类: Javascript Dojo扩展 (dojox)2011-05-18 19:13 2211人阅 ...

  7. dojo 官方翻译 dojo/json 版本1.10

    官方地址:http://dojotoolkit.org/reference-guide/1.10/dojo/json.html#dojo-json require(["dojo/json&q ...

  8. opencv python下载_[福利] OpenCV4 Python 最新中文版官方教程来了(附下载)

    教程简介 OpenCV 是计算机视觉中经典的专用库,然而其中文版官方教程久久不来.近日,一款最新 OpenCV4.1 版本的完整中文版官方教程出炉,读者朋友可以更好的学习了解 OpenCV 相关细节. ...

  9. basler相机参数简要中文说明_附下载| OpenCV最新中文版官方教程

    OpenCV是计算机视觉中经典的专用库,然而其中文版官方教程久久不来.近日,一款最新OpenCV4.1 版本的完整中文版官方教程出炉,读者朋友可以更好的学习了解OpenCV相关细节.教程根据官方提供的 ...

最新文章

  1. Informatica:当好大数据的清道夫
  2. 算法导论 习题24.2-4 amp; 24.3-6 单源最短路径问题
  3. python手机版安卓-当python遇到Android手机 那么,万物皆可盘
  4. spring boot 及微服务 学习笔记
  5. Rails 定时任务——whenever实现周期性任务
  6. 实时获取ccd图像_四元数数控:CCD视觉检测定位系统在玻璃瓶缺陷的检测
  7. 如何在keil下实现单工程多目标的设置(选择性自动编译)
  8. Android学习指南
  9. 线程名称的获取与修改
  10. python操作Excel文件
  11. 使用Flask-SocketIO完成服务端和客户端的双向通信
  12. php微博发布时间,PHP格式化显示时间函数,用于微博、社交媒体等,类似豆瓣
  13. Spring MVC 切面 ResponseBodyAdvice 对返回值增强
  14. Android OpenCV 摄像头实时预览
  15. Zoom视频会议软件
  16. swift - enumerated()
  17. gif动图怎么制作?手把手教你视频转gif动图
  18. Home键监听与电源键
  19. nonce值是什么?(Number once)(Number used once)cnonce(client nonce)(一个只被使用一次的任意或非重复的随机数值)
  20. css多行文本换行时出现右边参差不齐结局方案

热门文章

  1. 微信小程序支付签名生成(客户端)
  2. wp手机开发之获取汉字拼音的首字母
  3. 当心长角怪生物...闪动你的招牌...
  4. 【软件工程】概念模型、逻辑模型、物理模型
  5. 红光光浴一次能排多少湿气?-红光光浴/种光光学
  6. 波特兰:特别奖金3月PADNUG与Adam Cogan会面
  7. 如何快速实现抖音分享与第三方登录?
  8. Android 手机上获取手机当前上网IP地址(手机网关给手机号分配的IP)
  9. 百度地图marker标注上如何加上数字
  10. 时隔14年《头文字D》演员重聚,周杰伦余文乐刘畊宏昆凌同框,唯独少了陈冠希