为什么使用Dojo toolkit的十大原因

1年前 (2024-04-22)

最强大但是使用量却大大低于预期的Javascript工具类库肯定是:Dojo Tookkit。几乎所有的javascript框架或者类库都许诺你可以实现任何功能,但是Dojo是有此类话语权的类库。在这篇文章中,我们将从十个不同的角度来分享,为什么你应该在你的web项目中开始使用Dojo toolkit。

原因一:模块化和AMD模块加载机制

随着web技术的发展,客户端的javascript越来越复杂,为了更好,更快运行我们的js应用,我们需要模块化我们的程序。不使用异步加载的日子应该结束了。Dojo toolkit一直都引以骄傲他们的模块化设计,使用dojo.require来动态的加载页面资源。 虽然有一个跨域选项是异步的饿,缺省的加载javascript资源的方法是同步的。

Dojo已经迁移到了异步加载器上,由Rawld Gill开发,可以方便的异步加载所有资源,很大程度的提高了速度。为了加载js资源,你可以使用如下代码:

// require方法指导加载器去加载个数组的资源
// 如果资源已经被加载,缓存的对象会被使用
require(
   // 用来加载的模块
   ["dojo/on", "dojo/touch", "dijit/form/Button", "dojo/domReady!"],
 
   // 一个回调函数用来使用参数来加载模块  
   // 必须添加到和加载时一样的顺序
   function(on, touch, Button) {
      // 加载后执行其它
});

为了定义一个模块,使用如下模式:

// Using 'define' instead of 'require' because we're defining a module
define(
 
   // Again, an array of module dependencies for the module we'd like to build
   ["dojo/aspect", "dojo/_base/declare", "dijit/layout/BorderContainer"]
 
   // Again, a callback function which should return an object
   function(aspect, declare, BorderContainer) {
 
      // Return a module (object, function, or Dojo declared class)
      return declare("mynamespace.layout.CustomBorderContainer", [BorderContainer], {
 
         // Custom attributes and methods here
 
      });
 
})

这里我们使用简单的define方法来定义,基本上所有的AMD加载器都使用,非常简单的结构化方式。很像require,所以使用非常简单。所有列出的有依赖的数组项目都在callback运行之前调用。通常callback返回一个方法或者对象用来展现模块。一个简单的模式快速加载,管理模块,允许开发人员加载他需要的部分。

Dojo toolkit的特性丰富的加载器提供了插件,例如domReady,用来DOM,并且可以检测是否有相关JS。

// This code is featured in the dojo/Deferred module
define([
   "./has",
   "./_base/lang",
   "./errors/CancelError",
   "./promise/Promise",
   "./has!config-deferredInstrumentation?./promise/instrumentation"
], function(has, lang, CancelError, Promise, instrumentation){
 
   // ...
 
});

不单单提供了模块化,而且提供了直接使用的加载器。

相关资源:

1.The Dojo Loader

2.Asynchronous Modules Come to Dojo 1.6

3.Defining Modules

原因二:使用dojo/declare来实现Class和扩展性

javascript并不是真正的提供class系统,而Dojo toolkit通过dojo/declare提供了一个类似class继承机制。declare在整个框架中都被使用,所以开发人员可以:

1.剪切或者删除重复的代码

2.使用“混”方式来在不同class中共享功能

3.很简单的扩展已存在的class用来扩展自定义

4.不同项目中分享模块代码

5.在出现bug的Dojo class中安全的创建混的class

Dojo的class系统使用原型继承,允许原型(prototype)被继承,这样子class可以像父class一样强大。使用dojo/declare非常简单:

// Of course we need to use define to create the module
define([
   // Load dojo/declare dependency
   "dojo/declare",
 
   // Also load dependencies of the class we intend to create
   "dijit/form/Button",
   "dojo/on",
   "mynamespace/_MyButtonMixin" // Mixins start with "_"
], function(declare, Button, on, _MyButtonMixin) {
   
   // Return a declare() product, i.e. a class
   return declare(
 
      // First argument is the widget name, if you're creating one
      // Must be in object syntax format
      "mynamespace.CustomButton",
 
      // The second argument is a single object whose prototype will be used as a base for the new class
      // An array can also be used, for multiple inheritance
      [ Button, _MyButtonMixin ],
 
      // Lastly, an object which contains new properties and methods, or
      // different values for inherited properties and methods
      {
         myCustomProperty: true,
 
         value: "Hello!",
 
         myCustomMethod: function() {
            // Do stuff here!
         },
 
         methodThatOverridesParent: function(val) {
            this.myCustomMethod(val);
 
            // Calling "this.inherited(arguments)" runs the parent's method
            // of the same, passing the same params
            return this.inherited(arguments);
         }
      }
   );
});

以上代码并不能完成一个现实的任务(只是一个简单例子),通过了继承和混演示了代码重用。

另外一个使用dojo class系统的优势在于所有属性和方法都是可以自定义的,这里没有option来限制属性自定义的数量。任何东西都可以被修改或者扩展。

1.Definitive dojo/_base/declare

2.Classy JavaScript with dojo/_base/declare

3.Writing Your Own Widget

原因三:基于方面(Aspects)和“方法到方法的事件”

Aspects是高级web开发力最强大和必要的特性。Dojo toolkit提供了很多年这样的相关功能。允许你不使用传统的click,mouseover和keyup来触发功能。

允能够让你在触发function A之后或者之前触发function B 。你可以将方法链接起来,是不是很棒!

如下:

// after(target, methodName, advisingFunction, receiveArguments);
aspect.after(myObject, "someMethod", function(arg1, arg2) {
   
   // Execute functionality after the myObject.doSomething function fires
 
}, true);

保证function B在function A之前触发。

aspect.before(myObject, "someMethod", function(arg1, arg2) {
   
   // This function fires *before* the original myObject.someMethod does
 
});

Aspect对于使用Dijit来创建高级UI非常有帮助。针对事件来一个组件或者class能够触发另外一个组件的变化,允许开发人员通过使用很多小组件来创建一个大的可控制的组件:

var self = this;
aspect.after(this.submitButton, "onClick", function() {
 
   // The submit button was clicked, trigger more functionality
   self.showAjaxSpinner();
 
});

Aspect相关资源

1.dojo/aspect Documention and Examples

2.Using dojo/aspect