如何使用dojo.query 进行DOM查询和批量操作

入门

对DOM编程的一个关键要素是能够快速高效的获取到你所要使用的节点。之前我们曾经介绍过使用dojo.byId来查找DOM节点的方法。但是,这种方法的局限性也很明显。你很难为页面上每个节点都起一个唯一的ID;而且通过dojo.byId查找得到的总是单个节点,当你需要对一组节点做同样的动作时,dojo.byId 就无能为力了。解决这些局限的方法就是我们今天将要介绍的:dojo.query 。 dojo.query 方法使用了类似CSS查询的方式来获取一组节点,在新版的dojo当中,它甚至已经完全可以支持高级的CSS3 选择器(selector )了。

常用查询

为了演示一些最常用的DOM查询示例,我们假设了如下的一个HTML页面片段. (这是常见的包含一系列链接的HTML片段)

  1. <ulid="list">
  2. <liclass="odd">
  3. <divclass="bold">
  4. <aclass="odd">Odd</a>
  5. </div>
  6. </li>
  7. <liclass="even">
  8. <divclass="italic">
  9. <aclass="even">Even</a>
  10. </div>
  11. </li>
  12. <aclass="odd">Odd</a>
  13. <divclass="bold">
  14. <divclass="italic">
  15. <aclass="even">Even</a>
  16. </ul>
  17. <ulid="list2">
  18. <liclass="odd">Odd<li>
  19. </ul>

针对上述的HTML片段,能想到的第一个操作通常是如何获取到整个列表的一个句柄. 当然你可以用dojo.byId,但dojo.query 也可以达到同样目的. 虽然初看起来,你会觉得在这里dojo.query 不是那么方便,但结合后面的例子你就会发现它的好处。

view plain
    //获取所有包含节点ID为"list"节点的数组
  1. varlist=dojo.query("#list")[0];

通过在参数中加入"#",我们告诉dojo.query 去查找节点的"ID"属性。这是从CSS操作中借鉴来的语法。 需要注意的是dojo.query 的返回值永远是一个数组。 在这个例子中,因为只有一个ID叫"list" 的节点,所以我们直接取出了该数组的第一个元素。

上面我们看到了如何通过ID来获取节点,dojo.query 可不是只有这么点能力。它还支持通过class name来选择节点。假设我们希望能够获取所有class name等于"odd" 的节点:

//retrieveanarrayofnodeswiththeclassname"odd"
  • varodds=dojo.query(".odd");
  • 通过在参数中加入".",我们告诉dojo.query 现在是要匹配节点的className属性,这也是借鉴了CSS的语法。在这个例子中,dojo.query 将会返回包含4个<li> 节点和3个<a>节点 的数组。

    限定查询条件的作用域

    你可能已经发现了,在上一个例子中的得到odds数组同时包含了来自两个列表的节点。 假设我们只需要获取第一个列表中的odd节点呢? 有两种方法

    //使用选择器来限定查询的作用域
  • varodds1=dojo.query("#list.odd");
  • //使用第二个参数来限定查询的作用域
  • varodds2=dojo.query(".odd",dojo.byId("list"));
  • 这两种方法返回的都是相同的元素, 第一个方法使用了选择器的语法,限制了查询的结果在ID为list的元素内,而第二个方法则将一个节点作为限定查询参数传入query。

    当dojo.query 方法不包含第二个参数时,它会搜索整个DOM树结构,遍历<HTML>标签中包含的每个节点。 如果该方法调用时包含了一个DOM节点作为第二参数,这个节点就是查询的作用域, 查询的结果一定是该节点或其子节点。

    如果你的页面的DOM树结构比较小,比如像我们这里使用的列表的例子,那么省略第二参数的做法是可以的,也不会过分影响效率。但是如果页面很复杂,那么强烈建议你在使用dojo.query是明确指定第二参数来限定查询的作用域.这会大大减少无谓的对整个页面进行搜索操作从而提升速度和性能。

    为了方便,在接下来的例子中,我们都会省略第二个参数,不过请你一定要记住:在真实应用中你应该尽可能的制定作用域来让查询操作快速高效。

    更多高级的查询

    前面的例子中,我们查询得到的结果集包含了<li> 节点和<a> 节点两种,如果我们只想要其中的<a> 节点该如何做呢? 在dojo.query 查询时我们可以将 标签名和class 名组合作为查询条件:

    varoddA=dojo.query("a.odd");

    dojo.query 还支持另一种选择器, ">". CSS中使用">" 并不被所有浏览器支持,但是在dojo.query中却可以通用.

    使用这个选择器,查询会

    //获取任意一个有li节点作为其父节点的a节点
  • varallA=dojo.query("lia");
  • //获取任意一个有li节点作为其直接父节点的a节点
  • varsomeA=dojo.query("li>a");
  • 查看示例

    在我们的例子中,allA会查询出6个<a>节点,而someA只会包含2个<a>。 在">" 两侧可以使用任意的其他选择器,包括class 选择器。这里我们只是介绍了几种最常用的选择器,但dojo.query 是完全兼容CSS3的,还能够支持很多其他的选择器.你可以自己进一步学习掌握.

    NodeList(操作dojo.query返回的结果集)

    前文提到,dojo.query 返回的是匹配查询结果的所有节点构成的数组;这个数组实际上是一个特殊的数组对象称为dojo.NodeList, 该数组对象内建了一系列可以方便操作其中节点的方法.

    下面我们来看一下其中常用的一些方法, 在这个章节我们会使用下面的一个HTML代码片段:

    <divid="list">
  • <divclass="odd">One</div>
  • <divclass="even">Two</div>
  • <divclass="odd">Three</div>
  • <divclass="even">Four</div>
  • <divclass="odd">Five</div>
  • <divclass="even">Six</div>
  • </div>
  • dojo.NodeList 内建了一些Dojo 数组辅助方法. 例如forEach,它可以对数组中的每个元素执行一个函数:

    dojo.query(".odd").forEach(function(node,index,nodelist){
  • //针对query返回的数组中的每个节点,执行本方法
  • dojo.addClass(node,"red");
  • });
  • 被传入forEach的函数是一个回调函数,该回调函数支持3个参数: 当前正在操作的节点,该节点在数组中的位置序号,以及当前正在遍历的结果集(是一个dojo.NodeList 对象)

    对大多数开发者而言,第三个参数一般用不到,仅当你在回调函数中需要去操作结果集中的其他节点时需要用到这个参数. forEach方法还可以接受第二个参数,作为回调函数调用的作用域(Scope)

    dojo.NodeList中内建的其他数组辅助方法还包括: map,filter,every,和 some. 大多方法都返回一个dojo.NodeList 对象,因此很容易串联使用. some 和every是例外,它们返回值是布尔值(boolean)

    dojo.NodeList还内建了一些方面DOM操作的方法, 上一个例子还可以进一步简化为

    //向所有符合".odd"查询条件的节点加入className属性"red"
  • dojo.query(".odd").addClass("red");
  • //向所有符合".even"查询条件的节点加入className属性"blue"
  • dojo.query(".even").addClass("blue");
  • 这些DOM操作方法会在dojo.NodeList中每个节点上执行,同事返回值仍然是一个dojo.NodeList,可以串联使用.例如

    //所有符合".odd"条件的节点上删掉red属性而添加blue属性
  • dojo.query(".odd").removeClass("red").addClass("blue");
  • 其他dojo.NodeList 的DOM操作方法还包括: style,toggleClass,replaceClass,place 和empty. 所有这些方法都会返回dojo.NodeList,供串联使用.

    //把所有符合".even"条件的节点的字体颜色变为"while",并在节点上添加className"italic"
  • dojo.query(".even").style("color","white").addClass("italic");
  • 事件

    dojo.NodeList 上提供的另一重要方法是connect,用来连接DOM事件. 关于如何在Dojo中处理DOM事件会在下一个讲义中详细讨论,我们这里要解释一下如何使用dojo.NodeList的connect方法.

    特别要注意的是,虽然在dojo.NodeList上使用connect很方便,但是并不适用于dojo.NodeList 包含大量节点的情形,这种情况下应该使用一种称为事件代理(event delegation)的技巧.关于这一技巧我们会在未来的讲义中探讨.

    <buttonclass="hookUpdemoBtn">ClickMe!</button>
  • <buttonclass="hookUpToodemoBtn">ClickMe!</button>
  • <buttonclass="hookUpToodemoBtn">ClickMe!</button>
  • <buttonclass="hookUpdemoBtn">ClickMe!</button>
  • <mce:scripttype="text/javascript"><!--
  • //等待浏览器中DOM树完全加载完毕再执行操作
  • dojo.ready(function(){
  • //连接到所有符合".hookUp"条件的节点的"onclick"事件
  • dojo.query(".hookUp").connect("onclick",function(){
  • alert("Thisbuttonishookedup!");
  • });
  • //另一种连接事件的语法
  • dojo.query(".hookUpToo").onclick(function(){
  • alert("Thisbuttonishookeduptoo!");
  • });
  • //--></mce:script>
  • 上面的例子中我们演示了两种将dojo.NodeList连接到DOM事件的方法:

    通用的connect 方法, 参数中指定事件名称和回调函数

    使用一系列预定义的onXXXX 方法,完整的方法列表可以在参考手册中查找

    第二种做法更加简洁一些,但是内建的onXXX方法仅包含了标准的DOM事件, 对于一些非标准事件例如 DOMAttrModified, 则只能使用第一种方法.

    小结

    利用dojo.query 以及dojo.NodeList,对批量的DOM节点进行操作是很简单的:

    使用dojo.query 查询到你所需要操作的节点,再使用dojo.NodeList的内建方法对这些节点进行修改操作. 下面一章我们将会进一步介绍如何使用Dojo向页面中添加互动,如何使用dojo中的事件机制。

    版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

    相关推荐


    我有一个网格,可以根据更大的树结构编辑小块数据.为了更容易知道用户保存了什么,我希望当用户第一次看到网格时,网格处于不可编辑状态.当用户准备好后,他们可以单击编辑按钮,这将使网格的某些部分可编辑.然后,有一个保存或取消按钮可以保存更改或还原.在大多数情况下它是有效的.但
    我即将开始开发一款教育性的视频游戏.我已经决定以一种我可以轻松打包为Web,Mobiles和可能的Standalone版本的方式来实现这一目标.我不想使用Flash.因此,我确信(无论如何我会听取建议)使用JavaScript和SVG.我正在对这个问题进行大量研究,但我很难把各个部分放在一起.我知道Raphae
    我正在使用带有Grails2.3.9的Dojo1.9.DojoNumberTextBox小部件–我在表单中使用–将固定格式(JavaScript基本格式)的实数值(例如:12.56)设置为HTML表单输入字段(但根据浏览器区域设置显示/编辑它们,所以用户总是看到格式正确的数字).另一方面,Grails期望输入字段根据浏览器
    1.引言鉴于个人需求的转变,本系列将记录自学arcgisapiforjavaScript的学习历程,本篇将从最开始的arcgisapiforjavaScript部署开始,个人声明:博文不在传道受业解惑,旨在方便日后复习查阅。由于是自学,文章中可能会出现一些纰漏,请留言指出,不必留有情面哦!2.下载ArcGISforDe
    我正在阅读使用dojo’sdeclare进行类创建的语法.描述令人困惑:Thedeclarefunctionisdefinedinthedojo/_base/declaremodule.declareacceptsthreearguments:className,superClass,andproperties.ClassNameTheclassNameargumentrepresentsthenameofthec
    我的团队由更多的java人员和JavaScript经验丰富组成.我知道这个问题曾多次被问到,但为了弄清楚我的事实,我需要澄清一些事情,因为我在客户端技术方面的经验非常有限.我们决定使用GWT而不是纯JavaScript框架构建我们的解决方案(假设有更多的Java经验).这些是支持我的决定的事实.>
    路由dojo/framework/srcouting/README.mdcommitb682b06ace25eea86d190e56dd81042565b35ed1Dojo应用程序的路由路由FeaturesRoute配置路径参数RouterHistoryManagersHashHistoryStateHistoryMemoryHistoryOutletEventRouterContextInjectionOutl
    请原谅我的无知,因为我对jquery并不熟悉.是否有dojo.connect()的等价物?我找到了这个解决方案:http:/hink-robot.com/2009/06/hitch-object-oriented-event-handlers-with-jquery/但是没有断开功能!你知道jquery的其他解决方案吗?有jquery.connect但这个插件在我的测试中不起作用.
    与java类一样,在dojo里也可以定义constructor 构造函数,在创建一个实例时可以对需要的属性进行初始化。//定义一个类mqsy_yjvar mqsy_yj=declare(null,{     //thedefaultusername    username: "yanjun",          //theconstructor   
    我一直在寻找一些最佳实践,并想知道Dojo是否具有框架特定的最佳实践,还是最好只使用通用的Javascript标准?特别是我主要是寻找一些功能和类评论的指导方针?解决方法:对于初学者来说,这是项目的风格指南:DojoStyleGuide
    我有’05/17/2010’的价值我想通过使用dojo.date.locale将其作为“2010年5月17日”.我尝试过使用dojo.date.locale.parse,如下所示:x='05/17/2010'varx=dojo.date.locale.parse(x,{datePattern:"MM/dd/yyyy",selector:"date"});alert(x)这并没有给我所需的日期
    我正在尝试创建一个包含函数的dojo类,这些函数又调用此类中的其他函数,如下所示:dojo.provide("my.drawing");dojo.declare("my.drawing",null,{constructor:function(/*Object*/args){dojo.safeMixin(this,args);this.container=args[0];
    我知道你可以使用jQuery.noConflict为jQuery做这件事.有没有办法与Dojo做类似的事情?解决方法:我相信你可以.有关在页面上运行多个版本的Dojo,请参阅thispage.它很繁琐,但似乎是你正在寻找的东西.一般来说,Dojo和jQuery都非常小心,不会破坏彼此或其他任何人的变量名.
    我有一个EnhancedGrid,用户经常使用复杂的过滤器.有没有办法允许用户保存或标记过滤器,以便将来可以轻松地重新应用它?我知道我可以通过编程方式设置过滤器,但我无法预测用户想要的过滤器.谢谢!编辑:自己做了一些进展…使用grid.getFilter()返回过滤器的JSON表示,然后使用json.strin
    我有这个代码:dojo.declare("City",null,{constructor:function(cityid,cityinfo){}});dojo.declare("TPolyline",GPolyline,{constructor:function(points,color){},initialize:function(map){});应该是什
    我遇到的问题是我的所有javascript错误似乎来自dojo.xd.js或子模块.我正在使用chrome调试器和许多dijit功能,如dijit.declaration和dojo.parser.这有点烦人,因为它很难找到简单的错误或滑倒.我希望我可以添加一个选项,允许我的调试器在我的非dojo代码中显示选项会发生的位置.我是
    我正在使用DojoToolkit数字/解析函数来处理格式化和使用ICU模式语法解析字符串.有没有人知道有可能采取任意ICU模式字符串并以某种方式使用Dojo(或其他)库将其分解为它的部分(例如,对于数字模式,它可以被分解为小数位数,数千个分组等…).我希望这样做,而不需要让我的代码密切了
    我有两个看似相关的问题,访问在不同的地方定义的javascript函数.我遇到的第一个问题是调用我在firgbug或safari控制台中定义的函数.我定义了一个名为getRed的函数,如下所示:functiongetRed(row,col){//dosomethingstuffandreturntheredvalueasa
    我想添加一个在Ajax调用中指定的外部样式表.我已经找到了一种方法来使用jQuery(参见下面的示例),但是我需要使该方法适应dojoJavaScript框架.JQuery示例$('head').append('<linkrel="stylesheet"type="text/css"href="lightbox_stylesheet.css">');谢谢.解决方法:一旦你
    我正在尝试使用dojo.connect将onMouseDown事件连接到图像,如:dojo.connect(dojo.byId("workpic"),"onMouseDown",workpicDown);functionworkpicDown(){alert("mousedown");}类似的代码几行后,我将onMouse*事件连接到dojo.body确实完全正常工作.但是当我点击图像时