http://www.gbin1.com/technology/javascript/20120822-why-use-dojo-toolkit/
为什么使用Dojo toolkit的十大原因
日期:2012-8-22 来源:GBin1.com
最强大但是使用量却大大低于预期的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){ // ... });
不单单提供了模块化,而且提供了直接使用的加载器。
相关资源:
- The Dojo Loader
- Asynchronous Modules Come to Dojo 1.6
- Defining Modules
原因二:使用dojo/declare来实现Class和扩展性
javascript并不是真正的提供class系统,而Dojo toolkit通过dojo/declare提供了一个类似class继承机制。declare在整个框架中都被使用,所以开发人员可以:
- 剪切或者删除重复的代码
- 使用“混合”方式来在不同class中共享功能
- 很简单的扩展已存在的class用来扩展自定义
- 不同项目中分享模块代码
- 在出现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来限制属性自定义的数量。任何东西都可以被修改或者扩展。
- Definitive dojo/_base/declare
- Classy JavaScript with dojo/_base/declare
- 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相关资源
- dojo/aspect Documention and Examples
- Using dojo/aspect
原因四:Deferreds和统一的AJAX传输
Deferreds是基于对象的异步操作的表达方式,允许异步操作对象可以方便的从一个地方传递到另外一个地方。jQuery最近的最重要的添加就是Deferred。很巧合的是,Dojo团队已经实现了。Dojo toolkit几年前已经添加了这个特性,使用它来简化AJAX高级操作,动画及其其它。
除了最前面这里的Deferred对象,Dojo也在XMLHTTPRequest之外首次添加了几个IO处理方法,包括:window.name封装,AJAX文件上传的dojo/io/iframe及其其它。那么什么时候使用Deferredd对象呢?无论什么时候只要一个异步的AJAX操作发生!Deferred对象都会返回XHR请求,dojo/io请求,动画和其它!
// Fire an AJAX request, getting the Deferred in return var def = xhr.get({ url: "/getSomePage" }); // Do lots o' callbacks def.then(function(result) { result.prop = 'Something more'; return result; }).then(function(resultObjWithProp) { // .... }).then(function() { // .... });
那么dojo/io/iframe什么样子呢?
require(["dojo/io/iframe"], function(ioIframe){ // Send the request ioIframe.send({ form: "myform", url: "handler.php", handleAs: "json" // Handle the success result }).then(function(data){ // Do something // Handle the error case }, function(err){ // Handle Error }). then(function() { // More callbacks! }) });
Dojo中使用Deferred的好处自傲与每一个AJAX操作,不管什么方法,你都能够返回得到一个deferred,加速了开发和API整合。Dojo1.8将看到dojo/request的介绍,一个新的AJAX方法。这里有些例子将展示如何使用dojo/request API:
// The most basic of AJAX requests require(["dojo/request"], function(request){ request("request.html").then(function(response){ // do something with results }, function(err){ // handle an error condition }, function(evt){ // handle a progress event }); });
Deferred和AJAX资源
- dojo/request
- Ajax with Dojo
- Getting Jiggy with JSONP
- Dojo Deferreds and Promises
原因五:Dijit UI framework
毫无疑问,Dojo toolkit相比其它框架最大的优势在于Dijit UI框架。这个和其它工具吹嘘的完全不同:
- 完整,完整的支持本地化
- 完整的accessiblity
- 先进的布局组件能够帮助你解决100%高度元素,创建自定义的分割和布局修改
- 内建的表单验证和强化的用户体验
- 很多主题,最新的叫"claro"
- LESS文件自定义主题
- 非常模块化的代码,允许自定义和扩展
Dijit同时允许你宣示性的定义和程序化的创建组件,如下:
<div data-dojo-type="dijit.form.Button" data-dojo-props="label:'Visit GBin1.com!'"></div>
传统的js创建如下:
require(["dijit/form/Button"], function(Button) { // Create the button programmatically var button = new Button({ label: 'Visit GBin1.com!' }, "myNodeId"); });
Dijit UI资源
- The Famous Dijit Themetester
- Creating Template-based Widgets
- Layout with Dijit
- Dijit Themes, Buttons, and Textboxes
- Dijit Tutorials
原因六:Dojo Mobile
可以这么说,基本上每一个web问题,dojo都有一个解决方案,Dojo toolkit对于移动客户端的解决方案就是dojox/mobile,这个类库在我们以前的dojo移动开发文章中我们也牛刀小试了一把。如果你想看看dojox/mobile开发的UI界面,请点击这里:在线演示,dojox/mobile主要特性如下:
- 自动探测设备类型
- 拥有iOS,Andriod,Blackberry和common这四种主题
- mobile表单组件
- 布局组件和面板
- 支持桌面,允许简单的debug
移动组件可以使用宣示性或者程序化的方式实现。和Dijit组件类似。Mobile视图可以滞后加载并且不同的视图都是无缝切换,HTML很简答如下:
<!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no"/> <meta name="apple-mobile-web-app-capable" content="yes" /> <title>GBin1 Mobile Website</title> <!-- custom stylesheets will go here --> <!-- dojo/javascript will go here --> </head> <body> <!-- application will go here --> </body> </html>
使用dojox/mobile/deviceTheme,你可以自动检测到客户的主机类型并且应用正确的主题:
// Will apply the device theme base on UA detection require(["dojox/mobile/deviceTheme"]);
使用主题后,我们选择使用的组件,或者自定义class,如下:
// Pull in a few widgets require([ "dojox/mobile/ScrollableView", "dojox/mobile/Heading", "dojox/mobile/RoundRectList", "dojox/mobile/TabBar", "dojox/parser" ]);
一旦javascript资源请求后,我们就开始添加一些列的视图和组件了。
<!-- sample taken from Dojo's TweetView: http://dojotoolkit.org/documentation/tutorials/1.7/mobile/tweetview/app/ --> <!-- tweets view --> <div id="tweets" data-dojo-type="dojox.mobile.ScrollableView" data-dojo-props="selected: true"> <h1 data-dojo-type="dojox.mobile.Heading"> <!-- the refresh button --> <div data-dojo-type="dojox.mobile.ToolBarButton" data-dojo-props="icon: 'images/refresh.png'" class="mblDomButton tweetviewRefresh" style="float:right;"></div> Tweets </h1> <ul data-dojo-type="dojox.mobile.RoundRectList"> <li data-dojo-type="dojox.mobile.ListItem"> Tweet item here </li> </ul> </div> <!-- mentions view --> <div id="mentions" data-dojo-type="dojox.mobile.ScrollableView"> <h1 data-dojo-type="dojox.mobile.Heading"> <!-- the refresh button --> <div data-dojo-type="dojox.mobile.ToolBarButton" data-dojo-props="icon: 'images/refresh.png'" class="mblDomButton tweetviewRefresh" style="float:right;"></div> Mentions </h1> <ul data-dojo-type="dojox.mobile.RoundRectList"> <li data-dojo-type="dojox.mobile.ListItem"> Mention tweet item here </li> </ul> </div> <!-- settings view --> <div id="settings" data-dojo-type="dojox.mobile.ScrollableView"> <h1 data-dojo-type="dojox.mobile.Heading">Settings</h1> <h2 data-dojo-type="dojox.mobile.RoundRectCategory">Show</h2> <ul data-dojo-type="dojox.mobile.RoundRectList"> <li data-dojo-type="dojox.mobile.ListItem"> Setting item here </li> </ul> </div>
使用移动的组件和使用Dijit的方法非常类似。而且整个过程非常简单!
dojox/mobile资源
- Getting Started with dojox/mobile
- dojox/mobile tests
- 使用最新版本Dojo1.7的dojox/mobile开发移动设备web应用
原因七:GFX和图表
CSS动画是不错的视觉工具,既是动画图片,同时也是灵活和强大的矢量图形创建和管理工具。最流行的客户端的矢量图形生成工具一直是Raphael JS,但是Dojo toolkit的GFX类库毫无疑问更将的强大。GFX可以用来配置SVG,VML,Silverlight,Canvas和webGL格式的矢量图形。提供了一个健壮的封装来创建不同的矢量图片形状(线状图等等),包括:
- 改变大小,旋转和偏转
- 动画填入,拉直等属性
- 添加线或者圆圈图形到指定图形中
- 监听和响应鼠标属性
- 组合图形并且更好的去管理
创建代码如下:
require(["dojox/gfx", "dojo/domReady"], function(gfx) { gfx.renderer = "canvas"; // Create a GFX surface // Arguments: node, width, height surface = gfx.createSurface("surfaceElement", 400, 400); // Create a circle with a set "blue" color surface.createCircle({ cx: 50, cy: 50, rx: 50, r: 25 }).setFill("blue"); // Crate a circle with a set hex color surface.createCircle({ cx: 300, cy: 300, rx: 50, r: 25 }).setFill("#f00"); // Create a circle with a linear gradient surface.createRect({x: 180, y: 40, width: 200, height: 100 }). setFill({ type:"linear", x1: 0, y1: 0, //x: 0=>0, consistent gradient horizontally x2: 0, //y: 0=>420, changing gradient vertically y2: 420, colors: [ { offset: 0, color: "#003b80" }, { offset: 0.5, color: "#0072e5" }, { offset: 1, color: "#4ea1fc" } ] }); // Create a circle with a radial gradient surface.createEllipse({ cx: 120, cy: 260, rx: 100, ry: 100 }).setFill({ type: "radial", cx: 150, cy: 200, colors: [ { offset: 0, color: "#4ea1fc" }, { offset: 0.5, color: "#0072e5" }, { offset: 1, color: "#003b80" } ] }); });
生成形状如下:
基于GFX的强大类库就是dojox/charting。通过图表来展示视觉化的数据是非常不错的选择。dojox/charting提供了如下功能:
- 多个图表
- 动画图形元素
- 插件支持,包括MoveSlice(动画饼图),提示工具条,缩放和高亮
- 自更新的图表,由Dojo data store支持
一个基本的饼图如下:
<script> // x and y coordinates used for easy understanding of where they should display // Data represents website visits over a week period chartData = [ { x: 1, y: 19021 }, { x: 1, y: 12837 }, { x: 1, y: 12378 }, { x: 1, y: 21882 }, { x: 1, y: 17654 }, { x: 1, y: 15833 }, { x: 1, y: 16122 } ]; require([ // Require the widget parser "dojo/parser", // Require the basic 2d chart resource "dojox/charting/widget/Chart", // Require the theme of our choosing "dojox/charting/themes/Claro", // Charting plugins: // Require the Pie type of Plot "dojox/charting/plot2d/Pie" ]); </script> <!-- create the chart --> <div data-dojo-type="dojox.charting.widget.Chart" data-dojo-props="theme:dojox.charting.themes.Claro" id="viewsChart" style="width: 550px; height: 550px;"> <!-- Pie Chart: add the plot --> <div class="plot" name="default" type="Pie" radius="200" fontColor="#000" labelOffset="-20"></div> <!-- pieData is the data source --> <div class="series" name="Last Week's Visits" array="chartData"></div> </div>
当然这里有很多其它的例子。
dojox/gfx 和 dojox/charting资源
- Vector Graphics with Dojo’s GFX
- Interactive AJAX London Logo
- Dojo Charting
- Advanced Charting with Dojo
- Dojo GFX Demos
原因八:SitePen dgrid
Sitepen,Dojo toolkit创始人Dylan Schiemann的javascript咨询公司,打算替换Dojox的华而不实的Grid widget,使用更快,可扩展并且可编辑的Grid组件,主要特性如下:
- 支持不同的主题,配置简单
- 支持移动
- 行可排序
- 允许“滞后加载”grid数据
- 支持树状的Grid
- 使用Dijit widget支持可编辑的Grid
- 可扩展,支持列宽改变,拖放支持和分页,及其其它
SitePen已经做了很大的努力,取得了很大成功。
dgrid 资源
- dgrid Homepage
- dgrid iTunes Demo
- SitePen Blog
- dgrid GitHub repo
- dgrid Documentation
原因九:DOH测试框架
测试对于我们来说非常重要,特别是对于客户端而非服务器端的程序来说。随着不同的浏览器的出现,客户端的互动测试成为一个必须的内容和步骤。Dojo toolkit提供了自己的测试框架。别名DOH(Dojo objective Harness)。提供了每一个Dojo toolkit版本的下载。测试非常简答和明了:
// Declare out the name of the test module to make dojo's module loader happy. dojo.provide("my.test.module"); // Register a test suite doh.register("MyTests", [ // Tests can be just a simple function... function assertTrueTest(){ doh.assertTrue(true); doh.assertTrue(1); doh.assertTrue(!false); }, // ... or an object with name, setUp, tearDown, and runTest properties { name: "thingerTest", setUp: function(){ this.thingerToTest = new Thinger(); this.thingerToTest.doStuffToInit(); }, runTest: function(){ doh.assertEqual("blah", this.thingerToTest.blahProp); doh.assertFalse(this.thingerToTest.falseProp); // ... }, tearDown: function(){ } }, // ... ]);
上面的测试是一个非常简单的Dojo测试例子,如果面对更复杂的情况,例如,异步操作。比如是AJAX请求,DOH提供了一个非常简单的方式来测试。Deferred对象:
{ name: "Testing deferred interaction", timeout: 5000, runTest: function() { var deferred = new doh.Deferred(); myWidget.doAjaxAction().then(deferred.getTestCallback(function(){ doh.assertTrue(true); }); return deferred; } }
以上测试代码中,getTestCallack不会调用直到doAjaxAction完成,并且返回了成功或者失败。
DOH资源
- DOH Tutorial
- Nightly Tests
原因十:Dojo编译流程
当一个web应用准备部署时,对于创建一个压缩版的javascript对于加载速度和优化来说非常有必要。这有效的减少了请求次数,并且缩短了下载时间。Dojo的编译分析Define将调用并且检测依赖关系。使用Dojo toolkit编译流程,你需要创建一个build profile。它可以包含任何层次或者更加复杂,下面是一个例子:
var profile = { releaseDir: "/path/to/releaseDir", basePath: "..", action: "release", cssOptimize: "comments", mini: true, optimize: "closure", layerOptimize: "closure", stripConsole: "all", selectorEngine: "acme", layers: { "dojo/dojo": { include: [ "dojo/dojo", "app/main" ], customBase: true, boot: true } }, resourceTags: { amd: function (filename, mid) { return /\.js$/.test(filename); } } };
Dojo编译流程可自定义,允许:
- 压缩
- 如果创建组件的话,指定应用到CSS的压缩层次
- 输出
- 指定选择器引擎
- 更多
Build profile通过命令行来运行(最近为Node.js重写),提供了不同的选项来重写或者完成设置,下面一个例子:
./build.sh --profile /path/to/app/app.profile.js --require /path/to/app/boot.js
Dojo编译流提供了超棒的控制编辑文件的功能,帮助你压缩CSS和Javascript,这样你的Dojo程序将能够随时准备上线!
- Creating Builds
- The Dojo Build System
- Legacy Build Documentation
原因十一:Dojo的宝藏,更多Dojox
这里有很多的Dojo toolkit类库供你使用,相信你能找到你需要的所有功能。
- extra layout and form widgets for Dijit
- advanced, localized form validation routines
- WebSocket and long-polling wrappers
- image widgets, including lightbox, slideshow, and gallery utilities
- advanced IO helpers
- advanced drag and drop libraries
- Nodelist extensions
- Basic JavaScript language and helper utilities
- Advanced Javascript language and AJAX utilties
- On-demand asynchronous script loading
- A complete UI framework
- A comprehensive testing suite
- Build tools
- 更多
希望在大家的下一个项目中你能运用到Dojo toolkit,和jQuery相比,它功能更加的完善和强大。不过个人觉得如果你需要快速轻量级的解决方案,jQuery会更适合你。