Chinaunix首页 | 论坛 | 博客
  • 博客访问: 396507
  • 博文数量: 69
  • 博客积分: 1984
  • 博客等级: 上尉
  • 技术积分: 953
  • 用 户 组: 普通用户
  • 注册时间: 2007-03-28 00:43
个人简介

学无所长,一事无成

文章分类

全部博文(69)

文章存档

2015年(19)

2014年(14)

2013年(9)

2012年(17)

2010年(10)

我的朋友

分类: JavaScript

2014-07-08 12:45:38

原文:http://dojotoolkit.org/documentation/tutorials/1.10/nodelist_extensions/
难度等级:初级 Dojo 版本:1.10

起步

在前面讲解  的教程中,我们已经学习了如何使用查询串或选择器进行节点筛选,也学习了如何使用  的方法来操作节点。简短介绍后,下面是我们的 demos 会用到的标签(本文的主题是水果哦): 

dojo/NodeList object 同 DOM NodeList object 是不同的。 Dojo's NodeListis 是一个包含很多额外方法的数组对象实例。ES5 标准的循环方法都可用,即便是在非 ES5 环境下,后面还会介绍几个模块可以扩展 dojo/NodeList 添加一些有用的方法。

  1. <button type="button" id="btn">Pick out fresh fruits</button>
  2.  
  3. <h3>Fresh Fruits</h3>
  4. <ul id="freshList"></ul>
  5.  
  6. <h3>Fruits</h3>
  7. <ul>
  8.     <li class="fresh">Apples</li>
  9.     <li class="fresh">Persimmons</li>
  10.     <li class="fresh">Grapes</li>
  11.     <li class="fresh">Fresh Figs</li>
  12.     <li class="dried">Dates</li>
  13.     <li class="dried">Raisins</li>
  14.     <li class="dried">Prunes</li>
  15.     <li class="fresh dried">Apricots</li>
  16.     <li class="fresh">Peaches</li>
  17.     <li class="fresh">Bananas</li>
  18.     <li class="fresh">Cherries</li>
  19. </ul>

为演示 dojo/query,我们为 button 添加一个  click handler :

  1. require(["dojo/query", "dojo/domReady!"], function(query){
  2.     query("#btn").on("click", function(){
  3.         var nodes = query("li.fresh");
  4.         nodes.on("click", function(){
  5.             alert("I love fresh " + this.innerHTML);
  6.         });
  7.     });
  8. });


query("li.fresh") 调用会返回一个 NodeList,这是一个标准的 JavaScript 数组,附带一些方法可以方便我们操作 DOM nodes 集合。因为每个 query 调用都是返回 NodeList,我们可以进行链式调用简化工作(就不用一次又一次的定义 var nodes 了):

  1. require(["dojo/query", "dojo/domReady!"], function(query){
  2.     query("#btn").on("click", function(){
  3.         query("li.fresh").on("click", function(event){
  4.             alert("I love fresh " + event.target.innerHTML);
  5.         });
  6.     });
  7. });


View Demo

对于链式调用调试比较困难,因为调试器中没地方可以加日志或是断点。唯一的办法只有将调用链拆开,对每个调用逐个调试。

Doing More with NodeList

标准的获取节点,操作节点的方式在 Dojo 中已无处不在,而 NodeList 的潜在特性也很好的防止了同 Dojo 模块化特性相违背的设计,让我们可以集中精力,致力于设计 "组合式"的功能。遵循这个模式,在 Dojo 和 DojoX 中已经有了很多的 NodeList 扩展模块,需要时我们可以载入,给 NodeList 添加更多功能。现在让我们看一看吧。

A Note on Documentation

在 API 查看器中,除了列出 NodeList 对象外,还把所有在 Dojo 和 DojoX 扩展模块中声明的扩展内容一并列出了。其实就其源模块本身,远没有那么"复杂"。 In addition the individual modules which extend the object are essentially "blank"。在 reference guide 中,我们为每一个模块都建了一个描述页 (例如  page),用于清晰描述那个模块添加了什么方法。

Working with Styles and DOM

Dojo 1.7 以前,基本的 NodeList 特性已涵盖了很多 DOM 方法,如 addClass, removeClass,attr, style, empty, 和 place。自从  AMD 和 Dojo 1.7+ 出现后,这些方法统统被移到 。下面就是使用这个模块的例子:

  1. require(["dojo/query", "dojo/NodeList-dom"], function(query){
  2.     query("li.fresh")
  3.         .addClass("fresher")
  4.         .attr("title", "freshened")
  5.         .style("background", "lightblue")
  6.         .on("click", function(){
  7.             alert("I love fresh " + this.innerHTML);
  8.         });
  9. });



简单地加载 dojo/NodeList-dom 模块,NodeList 中就具有了这些方法。使用这个模块,跟使用 dojo/dom 和相关模块操作 DOM 是完全一样的。

动画元素-Animating Elements

The  module augments NodeList with a series of methods that allow you to apply effects from Dojo's effects system to a collection of nodes. These methods function identically to their non-NodeList counterparts, so take a look at the Dojo Effects and Animation tutorials if you aren't familiar with them.

这个 demo 中,我们还是用了同样的水果清单,button 被点击后会执行如下代码:

  1. require(["dojo/query", "dojo/NodeList-fx", "dojo/domReady!"], function(query){
  2.     query("#btn").on("click", function(){
  3.         query("li.fresh")
  4.             .slideTo({
  5.                 left: 200, auto: true
  6.             })
  7.             .animateProperty({
  8.                 properties: {
  9.                     backgroundColor: { start: "#fff", end: "#ffc" }
  10.                 }
  11.             })
  12.             .play();
  13.     });
  14. });
View Demo

Unlike most NodeList methods, NodeList-fx methods return an animation object by default, which conflicts with the normal chaining behavior of NodeList. This is because Dojo’s animation functions normally return an animation object, and it is up to you to callplay on that object to start the animation. To cause a NodeList-fx method to automatically play the animation and return a NodeList instead, set auto: true in the object passed to the function, as demonstrated above in the slideTo call.

将数据同元素关联-Associating Data with Elements

 模块提供了一种机制,使用 data 方法可以将任意数据添加到元素上。 Here is an example that stashes a Date object on an element each time it is clicked:

  1. require(["dojo/query", "dojo/NodeList-data", "dojo/domReady!"], function(query, NodeList){
  2.     function mark(){
  3.         var nodeList = new NodeList(this); // make a new NodeList from the clicked element
  4.         nodeList.data("updated", new Date()); // update the 'updated' key for this element via the NodeList
  5.     }
  6.  
  7.     query("li") // get all list items
  8.         .data("updated", new Date()) // set the initial data for each matching element
  9.         .on("click", mark); // add the event handler
  10.  
  11.     query("#btn").on("click", function(){
  12.         query("li").data("updated").forEach(function(date){
  13.             console.log(date.getTime());
  14.         });
  15.     });
  16. });



View Demo

这里,我们做了三件事:

  • 为每一个 element 关联一个初始化的 Date 对象。
  • 为点击事件设置了一个回调函数 mark() 。
  • 放置了一个 button ,可以让我们查看每个 item 的数据。

Inside the click handler, we still need a NodeList to get at the data properties for the clicked element, so we create a new one from the element that was clicked. The existing Date object on the clicked element is then replaced with a new one.

With NodeList-data, it is extremely important that you call removeData on theNodeList when removing elements from the DOM. If this is not done, your application will leak memory, since the data is not actually stored on the element itself and will not be garbage collected even if the node itself is.

Moving Around the DOM

The module adds methods to NodeList that allow you to easily move around the DOM to find parents, siblings, and children of reference nodes.

To illustrate, we’ll use a longer, categorized list of fruit. Some fruits have been marked as tasty (with the class of yum), and we want to be able to:

  1. Highlight them.
  2. Indicate in the header for that list that there’s goodness inside.

Using the methods provided by NodeList, dojo/NodeList-traverse and dojo/NodeList-dom, here is one quick way to do that:

  1. require(["dojo/query", "dojo/NodeList-traverse", "dojo/NodeList-dom",
  2.         "dojo/domReady!"], function(query){
  3.     query("li.yum") // get LI elements with the class 'yum'
  4.         .addClass("highlight") // add a 'highlight' class to those LI elements
  5.         .closest(".fruitList") // find the closest parent elements of those LIs with the class 'fruitList'
  6.         .prev() // get the previous sibling (headings in this case) of each of those fruitList elements
  7.         .addClass("happy") // add a 'happy' class to those headings
  8.         .style({backgroundPosition: "left", paddingLeft: "20px"}); // add some style properties to those headings
  9. });



View Demo

The chain here starts with an initial query to find the list nodes we're interested in, then uses traversal methods to move up and sideways to find the heading elements associated with the lists that contain those list nodes.

The important thing to understand with the traversal methods is that each call returns a newNodeList containing the results of your traversal. Methods like closest(), prev(), and next()are essentially sub-queries, with the nodes in the current NodeList being used as a reference point for the next sub-query. Most of these methods function identically to traversal methods in jQuery and should feel very familiar to users of that library.

Manipulating Elements

The extension module complements the traverse module by adding some methods for manipulating the nodes in a NodeList. This module adds methods mirroring jQuery's manipulation methods.

The following example puts some of these capabilities to use. Using the same categorized list of fruits, it builds two new lists of yummy and yucky fruits:

  1. require(["dojo/query", "dojo/NodeList-manipulate", "dojo/domReady!"],
  2. function(query){
  3.     query(".yum") // get elements with the class 'yum'
  4.         .clone() // create a new NodeList containing cloned copies of each element
  5.         .prepend('') // inject a span inside each of the cloned elements
  6.         .appendTo("#likes"); // insert the clones into the element with id 'likes'
  7.  
  8.     query(".yuck")
  9.         .clone()
  10.         .append('')
  11.         .appendTo("#dontLikes");
  12. });


View Demo

The key to this demo is the use of the clone method to create duplicates of the original elements. As with the NodeList-traverse methods, clone returns a new NodeList containing all newly cloned elements which are then modified and appended to the DOM. If clones were not created, the original elements would have been modified and moved instead.

Advanced Content Injection

The  module brings the advanced capabilities of  toNodeList. Here's a simple example of its use, in which we turn a simple list into a checkbox list using dijit/form/CheckBox widgets:

  1. require(["dojo/query", "dojo/_base/lang", "dijit/form/CheckBox", "dojo/NodeList-html", "dojo/domReady!"],
  2. function(query, lang){
  3.     var demo = {
  4.         addCheckboxes: function(q) {
  5.             query(q).html('', {
  6.                 onBegin: function(){
  7.                     var label = lang.trim(this.node.innerHTML),
  8.                         cont = this.content + label;
  9.                     cont = cont.replace('value=""', 'value="'+lang.trim(this.node.innerHTML) + '"');
  10.  
  11.                     this.content = cont;
  12.                     return this.inherited("onBegin", arguments);
  13.                 },
  14.                 parseContent: true
  15.             });
  16.         }
  17.     }
  18.  
  19.     query("#btn").on("click", lang.hitch(demo, "addCheckboxes", "li.alkaline"));
  20. });



View Demo

With the rich capabilities offered by other NodeList methods, especially those in NodeList-manipulate, the NodeList-html module is probably not one you will use very often, if at all. It is mentioned here nonetheless because it can still be useful as a specialized tool to solve a certain class of problems that would be much more difficult to solve in other ways.

小结

NodeList modules extend the existing NodeList API without bloating your code with features you won't use. By using some of these extensions in your code, you will be able to work with the DOM much more effectively and efficiently.



阅读(1476) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~