当前位置: 首页 > 工具软件 > Dojo > 使用案例 >

dojo框架的基本认识

林星华
2023-12-01

最近复用十几年前的一个项目,里面用到了dojo框架,so总结一下这个框架的一些重要的知识点

简介

Dojo的全称是Dojo Toolkit,始创于2004年,是当时各种蓬勃发展的JS工具包中的佼佼者。Dojo 为富互联网应用程序(RIA) 的开发提供了完整的端到端的解决方案,包括核心的 JavaScript 库,简单易用的小部件(Widget)系统和一个测试框架。

Dojo特性

Dojo Toolkit 的特性可以分到 4 个不同部分。这种划分使得开发人员可以将库大小保持到最小,确保应用程序性能不受大量 JavaScript 库下载的影响。例如,如果您只需要 Ajax 支持性能,您只需要包含 base 包;不需要包含扩展的 Dijit UI 组件。

Base

Base 包提供 Dojo Toolkit 的基础,包括一些功能,比如 DOM 使用函数、CSS3 基于选择器的 DOM 查询、事件处理、基本的动画、以及 Dojo 基于类的面向对象特性。

Core

Core 包包含一些 Base 中没有包含的附加特性。通常,这些特性不像 Base 中的特性那样频繁使用;因此,它们单独加载减轻 Base 包的负担。从这一点上来讲,Core 包提供一些实际有用的组件,包括高级动画拖放、I/O、数据管理、国际化(i18n)、浏览器历史管理。

Dijit

Dijit 包包含 Dojo 小部件和组件的扩展 UI 库。这些小部件的一些示例包括对话框、日历、调色板、工具提示和树。它也包括一些表单控件,这比标准 HTML 表单控件提供更多的功能,还有一些完整的布局管理选项。

DojoX

Dojo eXtensions (DojoX) 包含工具箱的各个子项目。位于 DojoX 中的大多数是实验特性,但是也有一些稳定组件和特性。

DOM操作方法

dojo.byId

dojo.byId 函数使您可以通过 id 属性选择一个 DOM 节点。该函数是标准document.getElementById 函数的一个别名,但是显然简短易书写。

dojo.query

虽然dojo.byId可以方便的根据id来获取一个DOM节点,但是根据id获取每一个元素几乎是不可能的,因为id是唯一标识。如果一次想获取几个元素,我们可以通过dojo.query方法。

dojo.body

dojo.body方法返回document的body元素

dojo.addOnLoad

现在我们想在window.onload里面处理一点东西,就像Ext.onReady,这个东西在dojo里叫做dojo.addOnLoad。

dojo.create

dojo.create方法创建一个元素

dojo.destroy

dojo.destroy方法会从父元素中删除该元素,并删掉该元素的所有子元素

dojo.empty

dojo.empty方法将删除掉所有子元素

dojo.forEach

dojo.forEach方法允许为数组或NodeList定义一个迭代器,来访问数组或NodeList中的每一项,并提供相应的操作。这个方法会忽略返回值,并且是不支持break的。

事件处理

dojo使用connect方法为DOM添加事件处理函数。

<script type="text/javascript">
      function btnClick() {
          alert("我被点击了");
      }
      var btn = dojo.byId("btn");
      dojo.connect(btn, "onclick", btnClick);
</script>

如果需要移除一个事件,则需要调用dojo.disconnect方法,这个方法需要一个dojo.connect方法的返回值作为参数:

var handle = dojo.connect(btn, "onclick", btnClick);
dojo.disconnect(handle);

订阅/发布

这是dojo很值得关注的一个功能,它使得各个dojo组件可以方便的交互。这个功能使用起来很方便:

<input type="text" name="txtMessage" value="" id="txtMessage" />
<input type="button" name="btn" value="发布…" id="btnPublish" />
<script type="text/javascript">
    dojo.addOnLoad(function () {
        //订阅MesagePublish主题
        dojo.subscribe("MessagePublish", function (msg) {
            alert(msg);
        });

        var btnPublish = dojo.byId("btnPublish");
        dojo.connect(btnPublish, "onclick", function () {
            //发布主题
            dojo.publish("MessagePublish", dojo.byId("txtMessage").value);
        });
    });
</script>

如要取消一个订阅,需要使用dojo.unsubscribe方法,这个方法需要一个由dojo.subscribe返回的句柄,其处理方式和dojo.connect、dojo.disconnect 的方式一样。

xmlhttp dojo.xhrGet

发出一个xmlhttp请求

function sayHello() {
    dojo.xhrGet({
        url: "http://localhost/hello/sayHello.jsp",
        handleAs: "text",
        load: function(responseText)
        {
          alert(responseText);
          dojo.byId("divHello").innerHTML = responseText;
        },
        error: function(response)
        {
          alert("Error");
        }
    });
}
dojo.connect(btn,"onclick",sayHello);

handleAs 把获取的内容作为text/html ;load 成功时的回调函数;error 失败时的回调函数

传入参数 

var params = {
    username:'Mark',
    id:'105'
}
dojo.xhrGet({
    url: "http://localhost/hello/sayHello.jsp",
    content:params,
    //...
});

 注意那个content参数,你要传入的参数是个关联数组/object,dojo会自动把参数解析出来,要使用post方法? dojo.xhrGet ---> dojo.xhrPost ,其他的还有,dojo.xhrPut、dojo.xhrDelete。

dojo.hitch 

 既然用到了xmlhttp,一个常见的问题就是回调函数的scope/context。在prototype、mootools里我们常用Function.bind,在dojo中,做相同事情的东西叫做dojo.hitch。

var handler = {
    name:'Mark',
    execute1: function(){
        dojo.xhrGet({
            url: "http://localhost/hello/sayHello.jsp",
            handleAs: "text",
            error: function(text)
            {
                console.dir(this);
                alert(this.name);//输出undefined,这里的this表示当前io参数
            }
            //...
        });
    },
    load: function(text){
        alert(this.name);
    },
    execute2: function(){
        dojo.xhrGet({
            url: "http://localhost/hello/sayHello.jsp",
            handleAs: "text",
            error: dojo.hitch(this,"load") //输出Mark
            //error: dojo.hitch(this,this.load); //与上一句相同,知道为什么要用方法名字而不是引用了吧?省去了长长的一串this.xxx
            //...
        });
    }
}

面向对象

(1)定义Class

dojo.declare("Customer",null,{
    constructor:function(name){
        this.name = name;
    },
    say:function(){
        alert("Hello " + this.name);
    },
    getDiscount:function(){
        alert("Discount is 1.0");
    }
});
var customer1 = new Customer("Mark");
customer1.say();

(2)继承

dojo.declare("VIP",Customer,{
    getDiscount:function(){
        alert("Discount is 0.8");
    }
});
var vip = new VIP("Mark");
vip.say();
vip.getDiscount();

(3)this.inherited方法调用父类

dojo.declare("VIP",Customer,{
    getDiscount:function(){
        this.inherited(arguments);
        //this.inherited("getDiscount",arguments);
    }
});

(4)关于构造函数 

constructor:function(args){
    var args = args || {};
    this.name = args.name;
    this.age = args.age;
}

(5)多继承,mixin  

dojo.declare("Customer",null,{
    say:function(){
        alert("Hello Customer");
    },
    getDiscount:function(){
        alert("Discount in Customer");
    }
});
dojo.declare("MixinClass",null,{
    say:function(){
        alert("Hello mixin");
    },
    foo:function(){
        alert("foo in MixinClass");
    }
});
dojo.declare("VIP",[Customer,MixinClass],{
});
var vip = new VIP();
vip.getDiscount();
vip.foo();
vip.say();//输出"Hello MixinClass"

子类自动获得父类和mixin的所有方法,后面的mixin的同名方法覆盖前面的方法。

package机制 

(1)dojo.require

dojo.require就是引入相应路径文件下的js文件。现在我们假设要用project/dojo-lib/dojo/string.js

dojo中的顶层目录就是dojo.js所在目录的上一层,即"project/dojo-lib/",而dojo.js放在project/dojo-lib/dojo/dojo.js 所以我们就这样:

dojo.require("dojo.string");

(2)dojo.provide

要自己编写一个package怎么办,那就利用dojo.provide。比如要写在:project/dojo-lib/com/javaeye/fyting/Package1.js 那么在对应的Package1.js中第一行需要这样写:

dojo.provide("com.javaeye.fyting.Package1");

(3)dojo.registerModulePath

那要是我写的js文件不想和dojo放在一起怎么办呢,那就用registerModulePath。假设要放在:

project/js/com/javaeye/fyting/Package2.js

Package2.js和上面的Package1.js一样的写法,不需要作特殊变化,就这样就行:

dojo.provide("com.javaeye.fyting.Package2");

在使用时,需要指名这个Package2.js所在的位置, 
dojo.registerModulePath("com","../../js/com"); 
只需要注意这里的相对路径是相对dojo.js来的。

我们假设所有以com.javaeye开头的js都放在一起,而com.microsoft的放在另外的地方,为了防止冲突,可以这样: 
dojo.registerModulePath("com.javaeye","../../js/com/javaeye"); 
dojo.registerModulePath("com.microsoft","../../javascript/com/microsoft");

 类似资料: