从Dojo1.6到Dojo1.8(三)—— Parser,Dijit,DojoX

前端之家收集整理的这篇文章主要介绍了从Dojo1.6到Dojo1.8(三)—— Parser,Dijit,DojoX前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

转载自:http://www.cnblogs.com/owenChen/archive/2012/12/25/2831311.html

前面两篇文章介绍了Dojo1.8的AMD以及Dojo core当中相关模块的变化。接下来我们介绍一下Dijit,Dojox这两个控件组件模块的变化。

Parser

在具体讲Dijit之前,我们先了解一下dojo/Parser模块,这个模块由原先dojo.parser转变而来。dojo对于控件的使用提供了编程式(programmatic)和声明式(declarative markup)两种方式。dojo/parser是用来翻译声明式的控件定义,并将它们渲染成控件的实例对象和控件相应的dom节点。

对于dojo/parser的调用方式如下:

require(["dojo/parser","dojo/ready"],function(parser,ready){
  ready(function(){
    parser.parse();
  });
});

尽管在dojoConfig中依然可以写parSEOnLoad:true的配置,但是还是需要手动去require parser模块。所以代码段中的方式是推荐的方式。

在dojo/parser内部最大的变化是增强了对于符合HTML5规范的属性支持。具体的举例如dojoType被改成data-dojo-type,对于控件属性的定义,也被统一放到data-dojo-props属性中。这种方式符合HTML5的属性定义规范。举例老的写法:

<button dojoType="dijit.form.Button" tabIndex=2
    iconClass="checkmark">OK</button>

新的写法将是:

<button data-dojo-type="dijit/form/Button" tabIndex=2
    data-dojo-props="iconClass: 'checkmark'">OK</button>

上面代码中的dijit/form/Button,替换了之前的dijit.form.Button,使用的是模块ID(MID),这也是我们之前在AMD的章节中讨论过的新写法。

这里需要注意的是,在使用某个MID之前,需要在require([...])调用中加载相应的模块,一般在<head>节点中,这样可以保证<body>中需要使用的控件都已经加载。

dijit widget

在1.8中,dijit包中的控件也遵循了新的模块方式的写法,即原先所有的全局的diji.*都被放到了各自相应的模块当中。如dijit.form.Button,现在为dijit/form/Button模块。

其实在dijit的这些变化当中,最先引起我注意的是dijit.byId()这个函数的变化。如今的dijit.byId()被移到了dijit/registry模块当中,相应的调用改成了registry.byId()。相应的dijit.byNode()也成了registry.byNode()。

下面我们具体介绍一下在dijit内部的一些机制和函数发生的变化,这些使我们在使用、扩展尤其是写自己的控件的时候需要注意的。

dojo/Stateful和dojo/Evented

在这里首先要引入在扩展或创建dijit时需要理解的两个比较重要的模块:dojo/Stateful和dojo/Evented。

dojo.Stateful提供了访问控件属性的统一接口:set()和get(),同时还提供了监测(watch)控件属性的能力。例如,你可以使用如下的代码

require(["dijit/form/Button","dojo/domReady!"],function(Button){
  var button = new Button({
    label: "A label"
  },"someNode");
 
  // Sets up a watch on button.label
  var handle = button.watch("label",function(attr,oldValue,newValue){
    console.log("button." + attr + " changed from '" + oldValue + "' to '" + newValue + "'");
  });
 
  // Gets the current label
  var label = button.get("label");
  console.log("button's current label: " + label);
 
  // This changes the value and should call the watch
  button.set("label","A different label");
 
  // This will stop watching button.label
  handle.unwatch();
 
  button.set("label","Even more different");
});

dojo/Evented的on()和emit()方法提供了事件监听和触发的功能。你可以有一下的写法:

define(["dojo/Evented","dojo/_base/declare"],function(Evented,declare){
  var MyComponent = declare([Evented],{
    startup: function(){
      // once we are done with startup,fire the "ready" event
      this.emit("ready",{});
    }
  });

  component = new MyComponent();
  component.on("ready",function(){
    // this will be called when the "ready" event is emitted
    // ...
  });
  component.startup();
});

on()方法被dijit引入用来做事件的绑定,后面会具体谈。

set(),get()

dojo1.6之前的版本,对于控件属性获取使用的是getValue(),setValue(),或者attr()方法。而现在使用的是统一的get()和set()方法。如下:

//老的写法
myEditor.getValue()
myTextBox.attr("value")
myForm.setValue(...);

//新的写法
myEditor.get("value")
myTextBox.get("value")
myForm.set("value",...);

watch(),on()

1.6及之前版本我们只能通过dojo.connect/this.connect来监测某些事件的发生,而1.8可以以更加优雅的方式来监测某些属性的变化或者方法调用。使用的方法是on()和watch().

//老的写法:
dojo.connect(myForm,"onValidStateChange",function(){ ... });
dojo.connect(myButton,"onClick",clickCallback);

//新的写法
myForm.watch("valid",function(name,oldVal,newVal){
  console.log(myForm.id + ": " + name + " changed from " +
  oldVal + " to " + newVal);
});
myButton.on("click",clickCallback);

基于模版的控件(Templated Widgets)

在1.6版本中的dijit._Templated被划分到了dijit/_TemplatedMixin和dijit/_WidgetsInTemplatedMixin两个模块。此外,dojoAttachPoint和dojoAttachEvent两个属性和事件的绑定也被改成了HTML5的形式:data-dojo-attach-point和data-dojo-attach-event。举例来说:

dojo.require("dojo.declare");
dojo.require("dijit._Widget");
dojo.require("dijit._Templated");

dojo.declare("SimpleTemplate",[dijit._Widget,dijit._Templated],{
  templateString: "<button><span dojoAttachPoint="label"></span></button>"
});

新的写法:

require(["dojo/declare","dijit/_WidgetBase","dijit/_TemplatedMixin"],function(declare,_WidgetBase,_TemplatedMixin){
  declare("SimpleTemplate",[_WidgetBase,_TemplatedMixin],{
    templateString: "<button><span data-dojo-attach-point="label"></span></button>"
  });
});

如果widget的template中包含其他的widget,需要使用_WidgetInTemplateMixin。

对于template文件的引用也发生了变化,不在支持templatePath,dojo.cache()也不再使用。

老的写法中对template的引用,会使用下面的写法:

templatePath: dojo.moduleUrl("templates","myTemplate.html")

而在新的控件定义中:

define([...,"dojo/text!./templates/myTemplate.html",function(...,myTemplate){
  ...
  templateString: myTemplate

另一个改变是控件中的waiRole和waiState属性不再支持,因为在现在的方式中可以更加直接的使用role和state属性。(查了一下,dojo的wai是跟accessbility resource相关的接口,大家可以Dijit Accessibility Resources这篇文章中去参考)。

this.connect(),this.subscribe(),this._supportingWidgets

这几个方法用来绑定控件的DOM元素事件或者某个内部方法调用,_supportingWidgets用来注册创建或者改变过的内部控件。这些本来都可以由dojo的基本事件来完成,如dojo.connect(),dojo.subscribe(),这里以this的方式来调用,主要是将这些事件绑定记录在控件内部,从而在控件被销毁的时候,释放和销毁这些事件的绑定,以避免内存泄漏的发生。

在1.8中,这几个方法不再被使用,取而代之的是this.own()函数来记录所有的这些内部的事件和控件。而事件绑定的函数则使用dojo标准模块中的接口如dojo/on,dojo/aspect,dojo/tpoic等。this.own()可以被多次调用,每次可以包含多个事件绑定或者控件的创建。这些被this.own()注册的事件绑定和控件会在控件被销毁的时候一起被释放和销毁。下面是一个可能的使用场景:

this.own(
  // setup an event handler (automatically remove() when I'm destroyed)
  on(this.domNode,"click",function(){ ... }),// watch external object (automatically unwatch() when I'm destroyed)
  aStatefulObject.watch("x",oVal,nVal){ ... }),// create a supporting (internal) widget,to be destroyed when I'm destroyed
  new MySupportingWidget(...)
);

DojoX

1.8中DojoX还是作为dojo包的一部分发布出来,但是到2.0的时候,DojoX的模块将被冲标准dojo包中移除。原先DojoX中的功能,有一部分将被移到Dojo和Dijit包中,还有一些将被放到另外的包当中。用户可以通过一些包管理工具从repository中获取

关于让我欢喜让我忧的Dojo Grid,将由新一代的GridX替代。GridX的架构完全不同于DataGrid和EnhancedGrid,它采用模块化的方式组织起来,提供了更加简洁和直接的接口,更加灵活和精简。尽管我没有用过GridX,但希望它能够在功能性能上都有更好的表现。

说实话,看到DojoX的这个变化我也有点吃惊,不过鉴于DojoX中的控件一直不是很稳定,而模块化轻量化也是现在前台框架发展的趋势,所以Dojo的这一动作也在情理之中。只是现在正在使用DojoX的朋友门要尽早做打算了,如果要升级到2.0的话还是会有很多的工作要做。正在准备使用1.8的朋友也要有一定的超前仪式,尽量避免对DojoX的过度依赖。使用AMD加载而不再使用dojox全局变量是必须要遵循的原则。

总结

好了,到这里我的这篇《从Dojo1.6到Dojo1.8》的系列文章(或翻译)终于介绍完了,希望能对关注Dojo的同学有所帮助,也希望能看到大家的评论和意见。

让我们一起期待Dojo2.0的发布吧,相信那会是Dojo新的春天!

猜你在找的Dojo相关文章