分享

Dojo基础

 LibraryPKU 2013-11-11

摘要

本文介绍了Dojo的基本相关信息,并通过一些简单示例让大家对Dojo有一个初步的感性认识。之后介绍了开发环境的准备以及在开发过程中需要具备的概念。

由于新版本的Dojo对以前的0.4版本上做了重大变革,而现有的很多资源还是基于原有版本进行介绍的,这难免会引起初学者的困惑。本文尽量使用深入浅出的方式,通过简短、平实的文字把Dojo介绍给大家,以便初学者可以很容易的了解Dojo,能够在最短时间内尽快的学习使用起来。

1.            Dojo介绍

1.1.    Dojo是什么

Dojo是一个使用Javascript编写的开源DHTML工具包。它建立在很多已捐献的代码基础之上,这就是为什么我们谈到它时,说它是一个"统一"的工具。利用Dojo,可以很容易地建立动态web页面以及其他支持Javascript的环境。可以使用Dojo封装的组件,它使web站点更具有可用性、更快速的响应、更多的功能。Dojo的事件系统,I/O API,和泛型语言增强组成了强大的程序环境的基础。可以使用Dojo建造工具来为Javascript代码编写命令行单元测试。可以使用Dojo 包来使得代码更容易去维护和更少的平台依赖。

1.2.    使用Dojo的好处

l         宽度和广度:Dojo是一个全堆栈的应用框架。不是那种把几个不同的源码简单拼凑在一起的组件。Dojo通过提供集成的底层架构和广泛的可选模块允许每个组件构造成一个高质量积木式的可信赖集合。这些组件给普通用户遇到的问题提供了良好的解决方案,他它们也很容易调整以满足各种需求。从基于面板的设计到客户端图表、到数据绑定、到久经考验的模块系统,Dojo是一个考虑了众多用户体验的刚性的底层架构。

l         质量:国际化以及易访问的底层架构是通过Dojo“纤维编织而成。每次击键都会有正确提示。所有组件作为一个粘着的整体契合在一起。每件东西都是可以很容易与CSS一起进行定制。只消稍做调整即可获得一个漂亮整洁的外观变化,以大量的用户体验为基础(这些人不仅有普通用户,还有设计师和开发人员)做了设计和测试,这些都是它的特点。

l         性能:Dojo被用于每天都有高访问量和高流量的站点上,采用Dojo的构造工具是为什么如此做的一个关键原因。Dojo软件包系统很容易管理大规模的UI开发项目以及构建顶部的系统层,可以做出令人吃惊的应用。所有这些无需代码修改。Dojo也把高性能的普通应用实现打包到了它的核心内,并且Dojo 0.9后的版本在性能上给予了更多的关注,减少了代码。它是个小巧、紧凑的工具包并且速度飞快。这些特点使Dojo成为扩展和构建的理想平台。

l         社区Dojo是一个开源的社区,个人和公司都能走到一起公平竞争,这使得大家在使用这些工具时彼此获益。所有开发都是在开放的环境中进行,并且有意识的降低学习门槛。

1.3.    Dojo的版本历史

Dojo项目历史有0.4.x,0.9,1.0.x等稳定版本,但0.9是对之前0.4.x的重大变革,与0.4.x是非兼容的,与其后的版本是兼容的。

由于Dojo项目的开发者已经把主要精力投入到新版本的开发维护上,所以本文是基于0.9以及后续版本的代码基础上进行分析。

截止到本文截稿时,Dojo最新的版本是1.0.2

1.4.    Dojo的安装

有三种方式安装Dojo:

1.     直接连接AOL的内容分布网络(CDN)。只要在网页中加入<script type="text/javascript" src="http://o./dojo/0.9.0/dojo/dojo.xd.js"></script>即可

2.     下载Dojo最新版本代码,安装在本机

3.     从配置管理服务器得到每日的build版本

1种方式无法深入代码内部去了解Dojo实现机制且需时刻在线,对于第3种方式的每日最新也无必要,只要有一个最稳定版本即可。第2种方式基本能弥补其他两种的不足,笔者本人推荐使用第2种方式。

1.5.    Dojo的包系统分解

Dojo主要分成4个包:dojo是核心,包括Ajax基础,以及事件、JSONCSS查询等基本内容;dijit包含了各种基于模板的布局、组件类,可以在它们的基础上直接使用或者继承定制;dojox是上述两个包的扩展包,提供了更加丰富绚丽的组件以及功能;util是辅助工具包。--from kswaking专栏

 

1.            简单示例

我们对任何事物的了解都是从感性认识开始的,所以在这里我们也用一个经典的“Hello world!”示例来表现Dojo的使用。

1.2.    代码分析

<html>

    <head>

        <title>Hello World</title>

        <style type="text/css">

            @import "../dojoroot/dojo1.0.2/dijit/themes/tundra/tundra.css";

            @import "../dojoroot/dojo1.0.2/dojo/resources/dojo.css"

        </style> <!--(1)-->

   

        <script type="text/javascript" src="../dojoroot/dojo1.0.2/"

                djConfig="parseOnLoad: true, isDebug: true"></script><!--(2)-->

               

       

        <script type="text/javascript">

            dojo.require("dojo.parser"); <!--(3)-->

            dojo.require("dijit.form.Button"); <!--(4)-->

           

           

        </script>

       

       

        <script type="text/javascript">    

           

            dojo.addOnLoad(function(){

                dojo.connect(dojo.byId('helloBtn'),

                'onclick',

                function(){

                    alert("Hello world!");

                }

                )

            });<!--(5)-->  

           

           

        </script>

    </head>

   

    <body class="tundra">

            <button dojoType="dijit.form.Button" id="helloBtn">Say Hello</button><!--(6)-->

    </body>

</html>

(1) <style type="text/css">

            @import "../scripts/dojo-1.0.2/dijit/themes/tundra/tundra.css";

            @import "../scripts/dojo-1.0.2/dojo/resources/dojo.css"

        </style>

引入css样式表的定义文件,示例使用的是dojo自带的css样式。可替换成我们自定义的样式文件。

(2) <script type="text/javascript" src="../scripts/dojo-1.0.2/dojo/dojo.js"

                djConfig="parseOnLoad: true, isDebug: true"></script>

     确定dojo.js文件的相对路径,由此确定使用dojo的方式编程,这是必需的。

     djConfig="parseOnLoad: true" (3)中的 dojo.require("dojo.parser");一起配合来使页面能使用Dojo的解析架构。

     djConfigDojo内置的一个全局对象,可以通过它来控制Dojo的行为。在本示例中,isDebugdjConfig的一个属性,设置是否为debug模式,如果为真,则console.debug的输出有效,这在开发时很有用,在发布时建议设置为false

(4) dojo.require("dijit.form.Button");声明将要使用的dojo的组件类型。类似Java中的import语句

(5) <script type="text/javascript">    

           

            dojo.addOnLoad(function(){

                dojo.connect(dojo.byId('helloBtn'),

                'onclick',

                function(){

                    alert("Hello world!");

                }

                )

            });

           

           

        </script>

dojo.addOnLoad表示在HTML页面加载后执行脚本程序

dojo.connect用于连接事件处理器(某一个函数)到一个元素或者一个对象。

(6) <button dojoType="dijit.form.Button" id="helloBtn">Say Hello</button>这是在页面中定义一个要使用的按钮控件,由dojoType属性指明可复用到的dojo组件类型是dijit.form.Button

1.3.    实现方式

1.3.1.      标签式实现

在页面中声明组件的方式可以像上面的示例一样,直接在标签中用dojoType对应的属性值来表明该组件对应的类型以及可实现的功能。

除此之外还有另一种实现方式,编程实现。

1.3.2.      编程实现

标签式实现需要在页面开发的时候,就要确定组件的类型、传入的参数,编程方式与之相比较就具有了更大的灵活性,参数可以动态生成以及页面与业务逻辑分离等多种好处。

下面我们用编程方式来举例来实现之前Hello World页面同样的功能。      

<html>

    <head>

        <title>Hello World</title>

        <style type="text/css">

            @import "../dojoroot/dojo1.0.2/dijit/themes/tundra/tundra.css";

            @import "../dojoroot/dojo1.0.2/dojo/resources/dojo.css"

        </style> <!--(1)-->

   

        <script type="text/javascript" src="../dojoroot/dojo1.0.2/"

                djConfig="parseOnLoad: true, isDebug: true"></script><!--(2)-->

               

       

        <script type="text/javascript">

            dojo.require("dojo.parser"); <!--(3)-->

            dojo.require("dijit.form.Button"); <!--(4)-->

           

           

        </script>

       

       

        <script type="text/javascript">    

            function constructHelloBtn(){

                var btnOutDiv=dojo.byId("btnOutDiv");

               

                helloBtnDiv=document.createElement("div");

                var helloBtn=new dijit.form.Button({id:"helloBtn",label:"Say Hello"},helloBtnDiv);

               

                btnOutDiv.appendChild(helloBtn.domNode);

               

                return helloBtn;

            }  

           

           

            dojo.addOnLoad(function(){<!--(5)-->

               

                var helloBtn=constructHelloBtn();   <!--(7)-->

               

                dojo.connect(dojo.byId('helloBtn'),

                'onclick',

                function(){

                    alert("Hello world!");

                }

                )

            });

           

           

        </script>

    </head>

   

    <body class="tundra">

            <div id="btnOutDiv"></div><!--(6)-->

    </body>

</html>

标识(1)(2)(3)(4)的形式、含义与之前完全一致,这里不再赘述。我们把关注点主要集中在(5)(6)(7)上。

先看(6),标签式实现要确定该组件的dojoType,以及参数,比如id。而编程方式实现只是定义一个html div组件作为将来放置动态生成的dojo组件的外层容器,唯一的id是为了将来查找该div做准备。

(5)处还是dojo.addOnLoad函数,表示在HTML页面加载时执行脚本程序,与之前代码不同的是,多了var helloBtn=constructHelloBtn();语句来构建一个按钮组件的实例。深入到自定义的constructHelloBtn()函数内部,我们可以看到,首先查找到在(6)处定义的div容器,之后新建一个dijit.form.Button的实例,其中设置id,label参数。这里是简单实现,我们可以想见其他诸如参数从某个配置文件动态读取后传入的方式。最后是把生成的该组件实例放入到外层div容器中用以显示。

1.            数据

1.1.    了解dojo.data

dojo.data提供了封装的标准的数据存取API,作为统一的数据访问层而存在。所有的数据都是item或者item的属性。Dojo.data提供了一个基本的ItemFileReadStore类来读取JSON格式数据,而dojox提供了更多扩展,比如XmlStore, CsvStore, OpmlStore等,我们也可以自定义自己的store类型。

dojo.data的操作都是异步的,可以不刷新页面而取回数据。

1.2.    dojo.data的一些术语与传统数据库的对比

dojo.data

传统数据库

备注

data source

数据库


datastore


item

行记录


attribute


reference


有些类似外键依赖,但外键指向的父记录,而reference指向子记录的列表

identity

主键


query

Where条件子句

从目前看,语法不如Where条件子句丰富,只支持and,不支持or

1.3.    JSON

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。它是基于Javascript标准的一个子集,JavaScriptd的数据结构(如字符串、数组、对象)的表示方式恰好与JSON相同,所以JSON可以被Javascript无损的识别。它是一种简单文本格式,与XML相比,它更加易读、更少的数据冗余。

一段典型的JSON格式数据形如:

{ identifier: 'name',
items: [
{ name: 'Adobo', aisle: 'Mexican' },
{ name: 'Balsamic vinegar', aisle: 'Condiments' },
{ name: 'Basil', aisle: 'Spices' },
{ name: 'Bay leaf', aisle: 'Spices' },
{ name: 'Beef Bouillon Granules', aisle: 'Soup' },
{ name: 'Vinegar', aisle: 'Condiments' },
{ name: 'White cooking wine', aisle: 'Condiments' },
{ name: 'Worcestershire Sauce', aisle: 'Condiments' }]

}

假设该段数据存放于pantry_spices.json文件,相应的Dojo datastore的声明和使用如下:

<div dojoType="dojo.data.ItemFileReadStore" jsId="pantryStore"
url="pantry_items.json"></div><!-(1)-->
<div
name="pantry_item" dojoType="dijit.form.FilteringSelect"
store="pantryStore"
searchAttr="name" value="Vinegar" autoComplete="true"
></div><!-(2)-->

(1) 指明了datastore的类型是dojo.data.ItemFileReadStore;数据的url,请注意这里除了可以是文件路径,也可以是一段请求得到的流;以及该datastorejsId

(2) 这里声明了dojoTypedijit.form.FilteringSelect的一个组件,该组件在html页面上展现形式为一个下拉框,需要有数据填充,其中store属性指向了jsIdpantryStore的一个datastore,由此把刚刚在(1)处定义的datastore的数据关联了起来。

1.4.    datastore的读取

var pantryStore = new dojo.data.ItemFileReadStore({url: "pantry_items.json" } ); //(1)

var gotList = function(items, request){ //(2)
var itemsList = "";
for (var i = 0; i < items.length; i++){
itemsList += pantryStore .getValue(items[i], "name") + " "; //(3)
}
alert("All items are: " + itemsList);
}
var gotError = function(error, request){ //(4)
alert("The request to the store failed. " + error);
}

pantryStore.fetch({onComplete: gotList, onError: gotError,query:{name:”*”}}); //(5)

(1) 此处用编程实现方式定义了一个datastore,在这里是dojo.data.ItemFileReadStore,其实还可以是其它的datastore类型,如XmlStore,CsvStore等,甚至可以是自定义的datastore类型。

(2) 自定义函数,为fetch函数做准备,用于数据处理。

(3) getValue函数,它是由dojo.data封装的API,用于得到某个item的某个属性名称的值。具体可参考Dojo API说明。

(4) 自定义函数,为fetch函数做准备,用于异常处理。

(5) 执行数据查询的语句,需要传入一些查询选项,比如在示例中出现的:

onComplete:在得到所有符合条件的数据后的处理函数,参数为item的列表;

onError:出现异常的处理函数;

query: 查询条件,是一个Object类型,形如{ name: '?hite*', aisle: 'Condiments' },”,”表示条件的and关系,通配符”?”,”*”表示一个或多个字符(包含0个);

此外,还有
queryOptions:
查询选项,指明是否忽略大小写或是否深度查找item的子;
onBegin:
在查询前的处理函数;
onItem:
在遇到符合条件的每一个item时的处理函数;
等。

还有一些其他的选项,具体可参考Dojo API说明。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多