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

学无所长,一事无成

文章分类

全部博文(69)

文章存档

2015年(19)

2014年(14)

2013年(9)

2012年(17)

2010年(10)

我的朋友

分类: JavaScript

2015-05-29 11:40:10

原文地址:

作者: Peter Higgins, Bill Keese, Tobias Klipstein, Nikolai Onken, Craig Riecke,

Dijit 是位于 Dojo 之上的组件系统 。如果你没有任何  ,那 Dijit 正好可以作为学习开端。你可以用很少的代码 甚至没有,就可以构建令人惊叹的 Web 2.0 GUI,当然理解学习 JavaScript 的路程可不短(而且你还要深入学习 HTML 和 CSS)。

有两种方式使用 Dijit :在常规 HTML 标签上加上特定标签的声明式 declaratively ,或者通过 JavaScript 的编程式programmatically  (你很快就会熟悉混合使用两种方式)。每一种方式设置的参数其实都一样。

  1. require(["dijit/Dialog", "dojo/domReady!"], function(Dialog){
  2.     // 创建一个"隐藏的" Dialog:
  3.     var myDialog = new Dialog({ title:"Hello Dijit!" }, "someId");
  4.     myDialog.startup();
  5.     // 提示:要打开这个dialog, 你必须调用
  6.     // myDialog.show();
  7. });

同如下方式等价:
  1. <script>
  2.      require(["dojo/parser", "dijit/Dialog"]);
  3. </script>
  4. <div data-dojo-type="dijit/Dialog" title="Hello Dijit!" id="someId"></div>

声明方式需要你 include  ,然后采用以下任一方式,或者将 dojoConfig.parseOnLoad 设置为 true,或者手工调用 parser.parse() (当你需要将 widgets 即 Dijits 创建出来的时候)。

注意: 访问 Dijit 使用函数  ... 这个同  是不同的,它完全是独立于 DomNodes 的。Dijit 会将所有 active widgets 储存在  中,用 id  作为唯一标识。 registry.byId() 根据传入的 ID 返回一个实例对象(即 widget),然后你就可以访问其内部的所有方法和属性了:

  1. <script>
  2.     require(["dojo/parser", "dijit/registry", "dojo/dom", "dojo/domReady!"], function(parser, registry, dom){
  3.         parser.parse();
  4.         // dom.byId("foobar") 只是一个普通的 domNode.
  5.         var myDialog = registry.byId("foobar");
  6.         myDialog.set("content", "

    I've been replaced!


    "
    );
  7.         myDialog.show();
  8.     });
  9. </script>
  10. <div data-dojo-type="dijit/Dialog" id="foobar" title="Foo!">
  11.    <p>I am some content</p>
  12. </div>

如果你需要引用对应 widget 的实实在在的 Node,那你可以使用 Dijit 属性: .domNode 。你可以通过此属性调整样式,位置,或进行 

  1. require(["dijit/registry", "dojo/dom-construct", "dojo/_base/window"], function(registry, domConstruct, win){
  2.      var thinger = registry.byId("foobar");
  3.      domConstruct.place(thinger.domNode, win.body(), "last");
  4.      // functionally equivalent to:
  5.      // win.body().appendChild(thinger.domNode);
  6. });

使用编程方式创建 widgets ,可以传入 id: ""参数:

  1. require(["dijit/Dialog", "dijit/registry"], function(Dialog, registry){
  2.     var myDialog = new Dialog({
  3.         id: "myDialog",
  4.         title: "Programmatic"
  5.     });
  6.     myDialog.startup();
  7.     // compare them:
  8.     console.log(registry.byId("myDialog") == myDialog);
  9. });

否则,系统会自动为你创建一个唯一 ID:

  1. require(["dijit/Dialog", "dijit/registry"], function(Dialog, registry){
  2.     var myDialog = new Dialog({ title:"No ID" })
  3.     console.log(myDialog.get("id"));
  4. })

所有的 Dijits 的编程方式都一样。使用 JavaScript new 函数创建一个对象实例,传入一个 object-hash ,用于包含属性和方法,然后提供一个可选的 “source node reference” 作为节点位置。
  1. require(["dijit/Dialog", "dojo/dom"], function(Dialog, dom){
  2.     var node = dom.byId("makeADialog");
  3.     var myDialog = new Dialog({ title:"From Source Node" }, node);
  4.     myDialog.show();
  5. });

以上代码会使得 creator使用  id=”makeADialog” 的节点,把它变成一个 。你可以直接传入 node 引用(如上述代码),也可以只是传入一个 id 字符串。任何一种方式都没关系,dojo.byId 会直接通过一个 reference(不做转换,字符串就会转换成 reference):

  1. require(["dijit/Dialog"], function(Dialog){
  2.     var myDialog = new Dialog({ title:"From Source byId" }, "makeADialog");
  3.     myDialog.show();
  4. });

属性

Widgets 跟 DOM 节点一样包含很多属性。属性是程序操作 widget 的主要接口之一,(有两种接口形式,另外一种接口是事件句柄,如 onClick(0。)。

set() 和 get()

 

普通的属性在初始化时设置值,在 widget 创建后也可随意修改。而对于如 "id" 和 "type" 等属性,已被标注为 [const],就只能在初始化时设置。还有一些属性如 “focused”,标注为 [readonly] 只读,就不能修改。

This basically mirrors how vanilla HTML DOM nodes work, although the syntax is a bit different. Specifically, to get/set attributes after initialization, you need to use the get() and set() methods:


  1. // set title
  2. myTitlePane.set('title', 'hello world');
  3. // find out if button is disabled
  4. var dis = myButton.get('disabled');
  5. // set to the current date
  6. myDateTextBox.set('value', new Date());

Set() 还有一种形式,类似 dojo/dom-style,可以传入 hash,便于一次设置多个属性:

  1. myInput.set({ tabIndex: 3, disabled: true, value: 'hi'});

watch()

 

属性值变化也可被监控。示例:

  1. myTitlePane.watch("open", function(attr, oldVal, newVal){
  2.    console.log("pane is now " + (newVal ? "opened" : "closed"));
  3. });

Dijits 的通用属性

有一些属性是所有 Dijit 实例都具备的通用属性。
 这些属性看起来很像是 widget 实例的成员函数,你可以通过前面讲的方法获取到一个 widget 的引用,然后通过引用就可以访问这些属性了。一些比较常用的属性如下:

  • domNode - widget 的顶层 node 。All widgets have a DOM Node attached to them, either through the srcNodeRef passed during instantiation, or a one created by the widget framework when declaring one programmatically. 这是一个真实存在的 DOM 节点,所有的 Dijits 都会有这么一个节点。如果你想显示或者隐藏一个 widget,很简单,像下面例子一样,修改 .domNode 节点的 CSS 属性中的 display 就可以了:
    1. require(["dojo/dom-style", "dijit/registry"], function(domStyle, registry){
    2.         // hide a widget with id="myThinger"
    3.         domStyle.set(registry.byId("myThinger").domNode, "display", "none");
    4. });
  • containerNode - 如果一个 widget 使用了 template 来创建复杂的标签结构,而且其内部包含 inner 标签用于显示内容的话, containerNode 成员就会指向这个用来容纳外部装入内容的节点。例如对于 ,外部环绕的 domNode 用来创建 widget ,而节点的具体内容是在 template's containerNode 的内部设置的。当使用 set() 函数来设置和加载内容时,我们针对的就是 containerNode 这个节点来处理内容。
  • declaredClass - this is actually a relic of , which is how widgets are defined. The declaredClass is a string equal to the fully qualified name of the widget class.
    1. require(["dijit/Dialog"], function(Dialog){
    2.     var myDialog = new Dialog({ title:"foo" }, "bar");
    3.     myDialog.declaredClass == "dijit/Dialog" // true
    4. });

 - 事件

用来处理 widgets 的另一类接口就是设置事件句柄 event handlers。例如:

  1. require(["dijit/form/Button"], function(Button){
  2.     new Button({
  3.         label: 'Click me!',
  4.         onClick: function(evt){ console.log("clicked!"); }
  5.     });
  6. });

事件句柄可以采用如上编程方式来设置,也可以直接声明,如下:

  1. <div data-dojo-type="dijit/form/Button">
  2.    <script type="dojo/on" data-dojo-event="click" data-dojo-args="evt">
  3.          console.log("clicked, event object is ", evt);
  4.    </script>
  5.    Click
  6. </div>
 

 - 主题风格

Dijit 有四种主题风格:Claro (Dojo 1.5+), Tundra, Soria, and Nihilo (all 1.0+)。 Themes are collections of images (icons and background images) and CSS, and bring a common visual style and color scheme to all the widgets. You can override the theme by container or by widget element to add nuance and flair.

To learn more about themes, see .

Everything in Dijit is designed to be globally accessible – to accommodate users with different languages and cultures as well as those with different abilities. Language translations, bi-directional text, and cultural representation of things like numbers and dates are all encapsulated within the widgets. Server interactions are done in a way that makes no assumptions about local conventions. All widgets are keyboard accessible and using the standard Dijit theme, usable in high-contrast mode as well as by screen readers. These features are baked in so that, as much as possible, all users are treated equally.

有很多种方式在页面中定位一个 widget ,然后通过其引用访问 widget。Widgets 就是对象 :包含一堆属性和 DomNode 引用。一旦你获取了一个 widget 的引用,你就可以使用其对象(或其成员属性)。有三种主要的方式访问一个 widget:

最简单的方式是通过 。一个 widget 创建出来,如果是使用了 Node 来创建的(比如使用了 srcNodeRef等),就有了一个 DOM 属性 id,这个 id 就会在  中注册成 widget 的 id。

先创建如下标签:

  1. <div id="myDialog" data-dojo-type="dijit/Dialog" title="A Dialog"><p class="innerContent">Content</p>/div>

通过对 myDiaog 调用 byId 我们就可以获取到  Dialog 实例:
  1. registry.byId("myDialog").show();

 
如果由于某种原因我们不知道 ID,那我们可以使用   函数,通过传入任意一个 DOM 子节点的引用来获取其上层 widget 。再次使用全面的标签页,如果将 widget 内部的 p element 传给 getEnclosingWidget 函数,我们同样得到了 Dialog 的引用:

  1. require(["dojo/query", "dijit/registry"], function(query, registry){
  2.     var node = query("p.innerContent")[0]; // 使用 query 来查找一个 dom 节点
  3.     var w = registry.getEnclosingWidget(node); // find the widget this node is in
  4.     w.show();
  5. });

最后一个也是最为通用的方法,同 getEnclosingWidget 非常类似,它仅仅在这种场景下使用,就是已知一个 widget 的 domNode 节点(即 template 中的顶级几点,或者被用来创建 widget 实例的 node,译注:即 new 的第二个参数 ):

  1. require(["dijit/registry"], function(registry){
  2.     var w = registry.byId("myDialog");
  3.     var node = w.domNode; // 这个例子只是用来展示 domNode 节点同 widget 的关系,不是好的写法,不要模仿
  4.     var widget = registry.byNode(node); // 现在两者是同一个东西了, w == widget
  5.     widget.show();
  6. });

注意: it typically doesn’t take that many lines to use 使用  一般用不到上面那么代码,上例只是精心设计用来展示 widgets 和其 domNode 属性之间的关系。使用 byNode 的一个典型场景就是在 widget 代码的外部处理事件句柄: 


  1. on(someNode, "click", function(e){
  2.     var w = registry.byNode(e.target);
  3.     if(w){ w.show(); }
  4. });

还有其他一些访问和操作 widgets 的方法,这些方法基本上都在  里面,a collection of all widgets active on a page.

一般来说,widgets 会创建他们自己的 DOM 结构。例如:

  1. require(["dijit/form/Button"], function(Button){
  2.     var myButton = new Button({label: "press me"});
  3. });

上述代码会创建一个新的 widget,随后可以利用 myButton.domNode 将其插入到文档中期望的位置。

采用声明式的语句如下:

  1. <button data-dojo-type="dijit/form/Button">press me</button>

注意在 dojo 扫描完节点属性并设置 innerHTML 后,原始的 button 节点已经被丢弃了。新的 DOM 节点自动替换掉了老的 button 节点。

可是,我们要知道还有另外一种类型的 widget 叫做 “behavioral widget”,这种 widget 只是修改原始节点(叫 srcNodeRef)而非取代它 。

要使用 behavioral widgets,你需要指定 source DOM node 供其操作。例如:

  1. require(["dojox/widget/FishEyeLite"], function(FishEyeLite){
  2.     new FishEyeLite({...}, "mySourceDom");
  3. });

如果是通过标签页来进行初始化就比较自然。比如一个 behavioral widget 给 anchor 添加一个确认对话框,代码大致如下:

  1. <a href="..." data-dojo-type="dojoc/widget/ConfirmAnchor">

Dijit 没有提供任何 behavioral widgets, 这种设计主要是考虑便于纯粹通过编程方式来设置组件 (不需要开发者创建任何的 sourceDOM 节点框架)。但对于某些程序来说这还是很有用,也不用担心 Dijit 还是支持他的。


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