地理信息系统(GIS)系列——Dojo 基础

1、Dojo 简介

Dojo 简介

  • Dojo 是一个 JavaScript 实现的开源 DHTML 工具包。它是在几个项目捐助基础上建立起来的(nWidgets,f(m),Burstlib)。Dojo 的最初目标是解决开发 DHTML 应用程序遇到的一些长期存在的历史问题,现在,Dojo 已经成为了开发 RIA 应用程序的利器。
  • Dojo 使得制作动态 Web 页面更加容易,您也可以在其它支持 JavaScript 的环境中使用 Dojo 。
  • 利用 Dojo 提供的组件,您可以提升 Web 应用程序的可用性和交互能力。
  • Dojo 很大程度上屏蔽了浏览器之间的差异性,因此,您可以不用担心 Web 页面是否在某些浏览器中可用。
  • 通过 Dojo 提供的工具,您还可以为代码编写命令行式的单元测试代码。
  • Dojo 的打包工具可以帮助您优化 JavaScript 代码,并且只生成部署应用程序所需的最小 Dojo 包集合。

Dojo 架构

  1. 语言库
  2. 特殊环境库
  3. 应用支撑库
  4. 工具包库

Dojo Toolkit 简介

Dojo Toolkit 是Dojo开发组件库。Dojo Toolkit 的特性可以分成 4 个不同的部分。

Dojo Toolkit 的特性——Base

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

Dojo Toolkit 的特性——Core

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

Dojo Toolkit 的特性——Dijit

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

Dojo Toolkit 的特性——DojoX

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

Dojo 包的整理

  • dojo.raise:抛出一个异常
  • dojo.errorToString:将异常转换为字符串
  • dojo.render:系统环境对象
  • dojo.hostenv.getText:返回指定url的内容
  • dojo.addOnLoad:可以加载指定函数到 window.load 时执行,好处就是可以很方便的在 window.load 时执行多个函数
  • dojo.exists:判断指定对象是否具有指定名称的方法
  • dojo.dom.isNode:测试指定对象是否为节点
  • dojo.dom.getUniqueId:取得唯一id
  • dojo.dom.removeNode:删除指定的节点
  • dojo.dom.getAncestors:返回指定节点的父节点集合
  • dojo.dom.innerXML:返回指定节点的XML
  • dojo.dom.createDocument:创建一个空的文档对象
  • dojo.dom.createDocumentFromText:根据文字创建一个文档对象
  • doc.load:根据文件装在XML
  • dojo.dom.prependChild:将指定的节点插入到父节点的最前面
  • dojo.dom.insertBefore:将指定的节点插入到参考节点的前面
  • dojo.dom.insertAfter:将指定的节点插入到参考节点的后面
  • dojo.dom.insertAtPosition:将指定的节点插入到参考节点的指定位置
  • dojo.dom.insertAtIndex:将指定的节点插入到参考节点的子节点中的指定索引的位置
  • dojo.dom.textContent:设置或获取指定节点的文本
  • dojo.dom.hasParent:判断指定节点是否有父节点
  • dojo.dom.isTag:判断节点是否具有指定的tag
  • dojo.dom.firstElement = dojo.dom.getFirstChildElement:取得指定节点下的第一个满足指定Tag条件的子节点
  • dojo.dom.lastElement = dojo.dom.getLastChildElement:取得指定节点下的最后一个满足指定Tag条件的子节点
  • dojo.dom.nextElement = dojo.dom.getNextSiblingElement:取得指定节点的下一个满足指定Tag条件的子节点
  • dojo.dom.prevElement = dojo.dom.getPreviousSiblingElement:取得指定节点的前一个满足指定Tag条件的子节点
  • dojo.dom.moveChildren:把指定节点下的所有子节点移动到目标节点下,并返回移动的节点数
  • dojo.dom.copyChildren:把指定节点下的所有子节点复制到目标节点下,并返回复制的节点数
  • dojo.dom.removeChildren:删除指定节点下的所有子节点,并返回删除的节点数
  • dojo.dom.replaceChildren:用指定的新节点替换父节点下的所有子节点
  • dojo.dom.getAncestorsByTag:返回所有符合指定Tag的指定节点的父节点集合
  • dojo.dom.getFirstAncestorByTag:返回最近的一个符合指定Tag的指定节点的父节点
  • dojo.dom.isDescendantOf:判断指定的节点是否为另一个节点的子孙
  • dojo.requireIf=dojo.requireAfterIf:可以根据指定的条件来决定是否加载指定的模块
  • dojo.debug:输出调试信息,如果在djConfig中指定了debugContainerId,则输出到指定的console容器中,否则直接 document.write
  • dojo.hostenv.println:与dojo.debug类似,不同的是,输出内容没有 DEBUG
  • dojo.io:不同的 IO 传输方式。 script、IFrame 等等;通过脚本或者iframe与服务器进行通信
  • Dojo.i18n:支持多个区域设置,可以与dojo.cldr协同工作
  • dojo.dnd:拖放功能的辅助 API
  • dojo.string:这个包可以对字符串进行如下的处理:修整、转换为大写、编码、esacpe、填充(pad)等等
  • dojo.parser:Html解析器
  • dojo.event:事件驱动的 API,支持 AOP 开发,以及主题 / 队列的功能
  • dojo.event模块下的:
  • dojo.event.browser.preventDefault:将当前事件的返回值设置为false
  • dojo.event.browser.stopPropagation:阻止Event传播
  • dojo.event.browser.callListener:调用监听器
  • dojo.event.browser.addListener:增加监听器
  • dojo.event.browser.removeListener;清除监听器(这个方法似乎是无效的)
  • dojo.event.browser.isEvent:判断指定对象是否为event对象
  • dojo.event.connect:绑定指定的方法到指定的对象的方法上,connect可以对任何对象的方法进行绑定,而不是只能针对DOM对象
  • dojo.event.connectBefore:dojo.event.connect默认是后绑定,connectBefore则是早绑定,绑定的方法将在指定方法前执行,用法与connect一致
  • dojo.event.connectOnce:connectOnce就是指保证只绑定一次,来避免重复绑定会导致的重复执行的问题
  • dojo.event.disconnect:解除绑定,调用参数与connect一致,即可解除之前的绑定操作
  • dojo.event.kwConnect:kwConnect可以做到更加灵活的绑定,比如可以设置延迟执行绑定
  • dojo.event.kwDisconnect:用来解除使用kwConnect指定的绑定
  • dojo.event.log:在执行指定对象的指定方法后自动记录日志
  • dojo.event.topic.destroy:删除主题,此主题所有的订阅都将失效
  • dojo.event.topic.unsubscribe:取消订阅主题
  • dojo.event.topic.subscribe:订阅主题
  • dojo.event.topic.registerPublisher:注册主题发布器
  • dojo.back:用来撤销用户操作的栈管理器;为那些不适用载入url来导航的应用程序提供返回按钮功能
  • dojo.reflect:提供反射功能的函数库
  • dojo.rpc:与后端服务(例如理解 JSON 语法的 Web 服务)进行通信;远程过程调用(RPC,Remote procedure call)框架
  • Dojo.regexp:用以帮助声称正则表达式功能
  • Dojo.number:解析、格式化国际化数字数据的功能
  • Dojo.cookie:简单http cookie控制
  • dojo.colors:颜色工具包
  • Dojo.currency:解析、格式化及国际化货币数据的功能
  • Dojo.date:解析、格式化及国际化时间数据的功能;解析日期格式的有效助手
  • dojo.data:Dojo 的统一数据访问接口,可以方便地读取 XML、JSON 等不同格式的数据文件;泛化数据源的访问功能以及数据源
  • dojo.fx:基本动画效果库,DOM效果
  • dojo.regexp:正则表达式处理函数库
  • dijit.forms:表单控件相关的 Widget 库
  • dijit.layout 页面布局 Widget 库
  • dijit.popup:这个包用于以弹出窗口方式使用 Widget
  • dojox.charting:用于在页面上画各种统计图表的工具包
  • dojox.collections:很有用的集合数据结构(List、Query、Set、Stack、Dictionary…)
  • dojox.encoding:实现加密功能的 API(Blowfish、MD5、Rijndael、SHA…)
  • dojox.math:数学函数(曲线、点、矩阵)
  • dojox.storage:将数据保存在本地存储中(例如,在浏览器中利用 Flash的本地存储来实现)
  • dojox.xml XML 解析工具包

Dojo 版 HelloWorld

<!DOCTYPE html>
<html >
<head>
    <title>Dojo版HelloWorld</title>
</head>
<body>
    <script type="text/javascript" src="dojo/dojo/dojo.js"></script>
    <script type="text/javascript">
        dojo.addOnLoad(function () {
            dojo.create("div", { innerHTML: "Hello world!" }, dojo.body());
        });
    </script>
</body>
</html>

2、DOM 操作

dojo.ready

  • 加载 dojo
dojo.ready(function(){});

dojo.byId

  • dojo.byId 函数使您可以通过 id 属性选择一个 DOM 节点。该函数是标准 document.getElementById 函数的一个别名,但是显然简短易书写。
dojo.byId("demo"); 				// 获取ID为demo的元素

dojo.query

  • 虽然dojo.byId可以方便的根据id来获取一个DOM节点,但是根据id获取每一个元素几乎是不可能的,因为id是唯一标识。如果一次想获取几个元素,我们可以通过dojo.query方法。
  • dojo.query 函数接受一个字符串参数,使用一个 CSS3 选择器引用您想选择的元素。这种操作方式很像jquery对DOM的操作。如果我们想获取页面中的某一个class的所有元素,只需要使用以下代码:
dojo.query(".class")
  • 这个方法将返回一个NodeList,我们可以通过遍历这个list来操作每一个元素。

dojo.body

  • dojo.body方法返回document的body元素。
console.log( dojo.body() );

dojo.create

dojo.create(str, attrs, refNode, pos)

str: 元素类型
attrs: 属性
refNode: 添加到哪里
pos: 添加到的位置
1. [null] 新创建的元素将作为refNode的子元素, 且添加到refNode中最后的位置 
2. [before] 新创建的元素将作为refNode的同辈元素, 且位于refNode的前边 
3. [after] 新创建的元素将作为refNode的同辈元素, 且位于refNode的后边 
4. [only] 新创建的元素将取代父元素内所有子元素, 添加到refNode内部 
5. [replace] 新创建的元素将直接替换点父元素 
6. [first] 新创建的元素将作为refNode的子元素, 并添加到所有子元素的最前边 
7. [last] 新创建的元素将作为refNode的子元素, 并添加到所有子元素的最后边

dojo.destroy

  • dojo.destroy方法会从父元素中删除该元素,并删掉该元素的所有子元素
var node = dojo.byId("node");
dojo.empty(node); 					// 删除节点的所有子节点(简单描述: 清空节点)
dojo.destroy(node);					// 删除节点及其所有子点(简单描述: 删除节点)

示例代码

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>    
    <script type="text/javascript" src="dojo/dojo/dojo.js"></script>
    <link rel="stylesheet" href="dojo/dijit/themes/claro/claro.css"/>
    <script type="text/javascript" >
        dojo.ready(function () {
           	var div1 = dojo.byId("div1");
           	div1.innerHTML = "我是DIV1";
            var div2 = dojo.query("#div1")[0];
            div2.innerHTML = "我是query";
            
            dojo.create("div", { innerHTML: "<p>hi</p>" }, dojo.body());
            dojo.empty(div2);
            dojo.destroy(div2);
        });
    </script>
</head>
<body>
    <div id="div1"></div>
</body>
</html>

3、Dojo 面向对象

Dojo 类的声明

dojo.declare(className, superclass, props);
  • className定义了类型的名称。
  • superclass指定了父类型,如果想声明的类并不存在父类,那么superclass可以为null。由于在Dojo中支持多继承,因此superclass可以是一个包含了所有父类的数组。
  • props是一个对象,其中包含了该类的所有字段以及方法。在props中可以定义一个特殊的函数constructor,constructor在该类型被实例化的时候会被自动调用到,相当于构造函数。
    示例:
define(["dojo/_base/declare"], function (declare) {
    return declare("person", null, {
        name: "zhangsan",
        constructor: function (name) {
            this.name = name;
        },
        say: function () {
            return this.name;
        }
    });
});
dojo.declare(null,
    {
        id: "",
        info: { name: "", age: "" },
        staticValue: { count: 0 },
        constructor: function (id, name, age) {
            this.id = id;
            this.info.name = name;
            this.info.age = age
            this.staticValue.count++;
        }
    }
);

Dojo 类的继承

dojo.declare 除了能够声明类,还能对类进行扩展,进而达到继承目的。
示例代码:

// 定义“人”这个类
dojo.declare('People',null,{  
    name:'unknown name',  
    action:function(){  
        //do nothing  
    },  
    constructor:function(name){  
        this.name=name;  
    }  
});
// 定义学生这个类
dojo.declare('Student',People,{  
    school:'',  
    action:function(){  
        //I am studing  
    },  
    constructor:function(name,school){  
        this.school=school;  
    }  
});
// 类的使用
var s = new Student('Jack','Harvard');  
s.name    		// Jack  
s.school  		// Harvard  
s.action  		// I am studing

定义静态域

传统的面向对象语言都直接在语言层面上支持静态域的概念。例如JAVA,其静态域包括静态类型的字段以及方法,静态类型的字段由所有的实例共享,而静态方法可以由类型直接调用,故其中不能访问非静态字段(只能先产生实例,在通过实例访问字段)。JS并没有直接支持静态域这个概念,但可以通过模拟的方式来达到静态域的效果。下面一个例子展示了Dojo中如何定义静态域:

dojo.declare("Foo", null, {  
    staticFields: { num: 0 },  
    add:function(){  
        this.staticFields.num++;  
    }  
});  
var f1=new Foo();  
var f2=new Foo();  
f1.add();  
f2.add();  
console.log(f1.staticFields.num);			// 2

// 调用父类方法
dojo.declare("Foo", null, {  
    constructor:function(){ console.log('foo') }  
});  
dojo.declare("Bar", Foo, {  
    constructor:function(){ console.log('bar') }  
});  
var b = new Bar; 							// 自动调用,打印foo bar

定义扩展(extend)

extend对类型进行扩展,增加原先没有的新属性或方法。当然也可以用它来添加重名的属性,不过这样会有一定的风险替换掉原先已经定义的属性。

dojo.declare('A',null,{  
    func1:function(){ console.log('fun1')}  
});  
A.extend({  
    func1:function(){ console.log('fun2')},  
    func2:function(){ console.log('fun3')}  
});  
var a=new A;  
a.func1();      							// fun2  
a.func2();

示例代码:

<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
     <script type="text/javascript" src="/dojo/dojo/dojo.js"></script>
    <script>
        dojo.require("dijit.form.Button");
        dojo.require("dijit.util");
    </script>
     <script type="text/javascript" >
    
         dojo.ready(function () {             
             dojo.declare('A', null, {
                 func1: function () { dojo.byId("div1").innerHTML = 'fun1'; }
             });
             A.extend({
                 func1: function () { dojo.byId("div2").innerHTML = 'fun2'; },
                 func2: function () { dojo.byId("div3").innerHTML = 'fun3'; }
             });
             var a = new A;
             a.func1();      //fun2  
             a.func2();
             var u = new util();
             dojo.byId("div3").innerHTML = u.color;

         });
    </script>
</head>
<body>
    <div id="div1"></div>
    <div id="div2"></div>
    <div id="div3"></div>
</body>
</html>

4、Dojo 常用函数

Require 函数

Require函数的作用主要是引入组件和模块。

dojo.require("dijit.form.Button");

新的使用方法:

require([
		"dijit/form/Button", 
		"dojox/layout/ContentPane", 
		...
	], function(
		Button, 
		ContentPane, 
		...
	){
	 
	});

Define 函数

作用是定义一个模块(module)。这个模块可以被require引用,引用了之后就可以使用define里面的东西。

define([ "dojo/dom"], function(dom) {  
    return {  
        setRed: function(id){  
            dom.byId(id).style.color = "red";  
        }  
    };  
});

Require 调用 Define 定义的模块:

<script>  
    require(  
        [ "dojo/ready", "test/util" ],  
        function(ready, util) {  
            ready(function() {  
                var id = "selected_text";  
                util.setRed(id);  
            });  
        });  
</script>  
## test/util.js

define(["dojo/dom"], function (dom) {
    return {
        setRed: function (id) {
            dom.byId(id).style.color = "red";
        }
    };
});

Request 函数

Request(URL, Option)

Request 函数用于处理ajax,异步通信。dojo/request函数(以及该模块下所有的发起请求的函数)的签名包含一个URL以及一个选项对象。这个选项对象中可以配置有关这次请求的各种参数。通常情况下使用dojo/request非常简单,只需要传递一个字符串,option参数是可省略的。下面是option对象中的常用配置参数:

option参数:
  • method:用于本请求的HTTP方法(默认是GET,dojo/request/script会忽略这个参数)
  • query:形如key=value的字符串,或者形如{key: ‘value’}的对象,包含所有的query参数
  • data:字符串或对象(会被dojo/io-query.objectToQuery串行化成字符串),表示需要发送的数据(GET和DELET请求会忽略这个参数)
  • handleAs:表示如何处理服务器端响应的字符串,默认"text",其他可能的值包括’json’, ‘javascript’,以及’xml’
  • headers:形如{‘Header-Name’: ‘value’}的对象,包含请求所需要的各种头部属性
  • timeout:表示等待多少毫秒算超时的整数,一旦超时将取消请求并"拒绝(reject)"所返回的promise
返回值

dojo/request所返回的promise对象具有一个普通promise没有的附加属性:response。这个属性本身也是一个promise,它将提供一个对象来更详细地描述这次响应:

  • url:发起请求的最终URL(加上了query字符串)
  • options:请求相关的参数
  • text:响应中数据的字符串表示
  • data:对响应进行处理后返回的数据(如果handles参数指定了有效的解析方式)
  • getHeader(headerName):用于获取请求头部参数的函数;如果某个provider没有提供头部信息,这个函数将返回null
Require(“dojo/request”,Function(request){
	Request(url,options).then(Function(data) {
		// 处理成功返回的数据
	}, function(err) {
		// 处理请求的失败
	}, function(evt) {
		// 处理progress事件
	});
});

Declare 函数

Declare函数定义类。

On 函数

On 函数是事件绑定函数。

// 绑定单击事件
on(myButton, "click", function(evt){
                    
});

示例代码:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
    <script >
        var dojoConfig = { baseUrl: "itfanr/", packages: [{name:"test",location:"test"}]};
    </script>
    <script src="dojo/dojo/dojo.js"></script>
    <script >
    //  	require(
    //   		["dojo/ready", "test/person"],
    //   		function (ready, person) {
    //      		ready(function () {
    //           		var id = "selected_text";
    //          		var person1 = new person("dfdsfd");
    //           		alert(person1.name);
    //      		});
    // 		});
    
        require(["dojo/on", "dojo/dom", "dojo/dom-style", "dojo/request", "dojo/mouse", "dojo/domReady!"], function (on, dom, domStyle,request,mouse) {
	        var myButton = dom.byId("myButton");
	        var myButton2 = dom.byId("myButton2"),
	        var myDiv = dom.byId("myDiv");
	
	        on(myButton2, "click", function (evt) {
	            request.get("TextFile.txt").then(
		            function (response) {
		                myDiv.innerHTML = "<pre>" + response + "</pre>";
		            },
		            function (error) {
		                myDiv.innerHTML = "<div class=\"error\">" + error + "<div>";
		        	}
		        );
	        });
	
	        on(myButton, "click", function (evt) {
	            domStyle.set(myDiv, "backgroundColor", "blue");
	        });
	        on(myDiv, mouse.enter, function (evt) {
	            domStyle.set(myDiv, "backgroundColor", "red");
	        });
	        on(myDiv, mouse.leave, function (evt) {
	            domStyle.set(myDiv, "backgroundColor", "");
	        });
	    });
    </script>
</head>
<body>
    <h1 id="selected_text">Hello</h1>
    <button id="myButton">单击ON</button>
    <button id="myButton2">单击Request</button>
    <div id="myDiv">myDiv</div>
</body>
</html>

5、Dojo 配置 dojoConfig、ContentPanes 和 FloatingPanes 面板

Dojo 配置 dojoConfig

  • dojoConfig用于设置一些在Dojo运行时的选项和默认的行为方式。
  • 首先要定义dojoConfig设置一些属性,然后加载dojo.js,如果这个过程反过来,那dojoConfig的配置则无效。
<script>
    dojoConfig = {
        has: {
            "dojo-firebug": true
        },
        parseOnLoad: false,
        foo: "bar",
        async: true,
        aliases:[
        	["ready", "dojo/domReady"],
        	["registry","dijit/registry"],
        	["dialog","dijit/Dialog"],
        	["parser","dojo/parser"]
        ],
        packages: [{
        	name: "js",
        	location: "/js"
        }],
        locale: location.search.match(/locale=([\w\-]+)/) ? RegExp.$1 : "en-us"
    };
</script>
has

has 用来设置一些 Dojo 支持的系统特性。

has: {	"dojo-firebug": true	}, 			// 加载Dojo版的Firebug调试环境

如果浏览器没有自带调试工具,可以用:

"dojo-debug-messages": true					// 显示调试信息

针对于一些废弃的或测试中的功能特性在运行时的信息。

Loader Configuration

加载时的一些常用选项。

parseOnLoad: true/false
parseOnLoad: true/false						// 是否在DOM和所有初始化完成后由dojo.parser解析页面
async
async: true/false/legacyAsync 				//是否异步加载
设置别名
aliases: [
    // [alias name, true name]
    ["cookie", "dojo/cookie"]
]
packages
packages: [{
    name: "myapp",
    location: "/js/myapp"
}]

提供包名及其路径。

locale

本地化与国际化。

locale: location.search.match(/locale=([\w\-]+)/) ? RegExp.$1 : "en-us"

示例代码:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>  
    <script >
        var dojoConfig = { baseUrl: "itfanr/", packages: [{name:"test",location:"test"}]};
    </script>
    <script src="dojo/dojo/dojo.js"></script>
    <script >
        require(
       	   ["dojo/ready", "test/person"],
	       function (ready, person) {
	           ready(function () {
	               var id = "selected_text";
	               var person1 = new person("小明");
	               alert(person1.name);
	           });
	       });
       
    </script>   
</head>
<body>
    <h1 id="selected_text">Hello</h1>
</body>
</html>

ContentPanes

ContentPanes 是所有小部件的基石,其他任何小部件都可以用它作为内容或者子小部件的载体。

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
    <script>dojoConfig = { parseOnLoad: true }</script>
    <link rel="stylesheet" href="dojo/dijit/themes/claro/claro.css" />
    <style type="text/css">
        @import "dojo/dojox/layout/resources/FloatingPane.css";
        @import "dojo/dojox/layout/resources/ResizeHandle.css";
    </style>
    <script src="dojo/dojo/dojo.js"></script>

    <script>
        require(["dojo/ready", "dijit/layout/ContentPane"], function (ready, ContentPane) {
            ready(function () {
                new ContentPane({
                    content: "<p>I am initial content</p>",
                    style: "height:125px"
                }).placeAt("targetID2");
            });
        });
    </script>
</head>
<body class="claro">
    <div id="targetID2"  style="background-color:red">
        A contentPane will appear here:
    </div>
</body>
</html>

FloatingPanes

FloatingPanes 浮动面板,可以模拟 Windows 窗口的效果在页面上随意拖动。

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
    <script>dojoConfig = { parseOnLoad: true }</script>
    <link rel="stylesheet" href="dojo/dijit/themes/claro/claro.css" />
    <style type="text/css">
        @import "dojo/dojox/layout/resources/FloatingPane.css";
        @import "dojo/dojox/layout/resources/ResizeHandle.css";
    </style>
    <script src="dojo/dojo/dojo.js"></script>

    <script>
        dojo.require("dojox.layout.FloatingPane");
        dojo.require("dijit.form.Button");
        var pFloatingPane;
        dojo.ready(function () {
            pFloatingPane = new dojox.layout.FloatingPane({
                title: "A floating pane",
                resizable: true, able: true,
                style: "position:absolute;top:0;left:0;width:100px;height:100px;visibility:hidden;",
                id: "pFloatingPane"
            }, dojo.byId("pFloatingPane"));

            pFloatingPane.startup();
        });
    </script>
</head>
<body class="claro">
    <div id="pFloatingPane">This is the content of the pane!</div>
    <div data-dojo-type="dijit.form.Button" data-dojo-props="label:'Show me', onClick:function(){pFloatingPane.show();}"></div>
    <br /><br /><br /><br />
</body>
</html>

6、BorderContainer 和堆叠容器

BorderContainer是一个布局容器,主要分为5个区域,上下左右中。
每个BorderContainer都有两种不同的方式布局,可以通过“design”属性来控制,分别是headline和sidebar。

headline

sidebar

堆叠容器

当页面中的内容比较多时候,可以使用堆叠容器显示部分元素,主要有3种类型:

  • StackContainer:最普遍的一种,需要自己编写控制和代码
  • AccordionContainer:导航按钮在面板内显示
  • TabContainer:按钮在前端一字排开
<!DOCTYPE html>
<html >
<head>
	<link rel="stylesheet" href="dojo/dijit/themes/claro/claro.css">
	<style type="text/css">
		html, body {
		    width: 100%;
		    height: 100%;
		    margin: 0;
		    overflow:hidden;
		}
		#borderContainerTwo {
		    width: 100%;
		    height: 100%;
		}
	</style>
	<script>dojoConfig = { parseOnLoad: true }</script>
	<script src='dojo/dojo/dojo.js'></script>
	<script>
	    // require(["dojo/parser", "dijit/layout/ContentPane", "dijit/layout/BorderContainer", "dijit/layout/TabContainer", "dijit/layout/AccordionContainer", "dijit/layout/AccordionPane"]);
	</script>
</head>
<body class="claro">
    <div data-dojo-type="dijit/layout/BorderContainer" data-dojo-props="gutters:true, liveSplitters:false" id="borderContainerTwo">
    <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'top', splitter:false">头部</div>
    <div data-dojo-type="dijit/layout/AccordionContainer" data-dojo-props="minSize:20, region:'right', splitter:true" style="width: 300px;" id="leftAccordion">
        <div data-dojo-type="dijit/layout/AccordionPane" title="项目一"></div>
        <div data-dojo-type="dijit/layout/AccordionPane" title="项目二"></div>
        <div data-dojo-type="dijit/layout/AccordionPane" title="项目三" selected="true"></div>
        <div data-dojo-type="dijit/layout/AccordionPane" title="项目四"></div>
    </div><!-- end AccordionContainer -->
    <div data-dojo-type="dijit/layout/TabContainer" data-dojo-props="region:'center', tabStrip:true">
        <div data-dojo-type="dijit/layout/ContentPane" title="My first tab" selected="true">查询</div>
        <div data-dojo-type="dijit/layout/ContentPane" title="My second tab">图表</div>
        <div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="closable:true" title="My last tab">数据</div>
    </div>
   	<div data-dojo-type="dijit/layout/ContentPane" data-dojo-props="region:'bottom'" style="background-color:red">底部</div>
</div><!-- end BorderContainer -->
</body>
</html>

7、自定义小部件和内部小部件基类

行为性小部件

这类小部件直接使用 DOM 树创建自己的 DOM 树。

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
    <link rel="stylesheet" href="dojo/dijit/themes/claro/claro.css"/>
    <script src='dojo/dojo/dojo.js'></script>
    <script>
        require([
     		"dojo/_base/declare", "dojo/parser", "dojo/ready", "dijit/_WidgetBase",
        ], function (declare, parser, ready, _WidgetBase) {

            declare("MyFirstBehavioralWidget", [_WidgetBase], {
                // put methods, attributes, etc. here
            });
            ready(function () {
                // Call the parser manually so it runs after our widget is defined, and page has finished loading
                parser.parse();
            });
        });
    </script>
</head>
<body>
    <span data-dojo-type="MyFirstBehavioralWidget">最简单的行为性小部件</span>
</body>
</html>

非行为性小部件

非行为性小部件,最低的要求是创建一个 DOM 树,小部件的 DOM 树保存到 domNode 属性中。

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
    <link rel="stylesheet" href="dojo/dijit/themes/claro/claro.css"/>
    <script src='dojo/dojo/dojo.js'></script>
    <script>
        require([
    		"dojo/_base/declare", "dojo/dom-construct", "dojo/parser", "dojo/ready", "dijit/_WidgetBase",
        ], function (declare, domConstruct, parser, ready, _WidgetBase) {
            declare("Counter", [_WidgetBase], {
                // counter
                _i: 0,

                buildRendering: function () {
                    this.domNode = domConstruct.create("button", { innerHTML: this._i });
                },

                postCreate: function () {
                    // every time the user clicks the button, increment the counter
                    this.connect(this.domNode, "onclick", "increment");
                },

                increment: function () {
                    this.domNode.innerHTML = ++this._i;
                }
            });

            ready(function () {
                // Call the parser manually so it runs after our widget is defined, and page has finished loading
                parser.parse();
            });
        });
    </script>
</head>
<body>
    <span data-dojo-type="Counter">最简单的非行为性小部件</span>
</body>
</html>

模块化小部件

使用 _TemplatedMixin 实现小部件定义与小部件行为的实现分离开,实现模块化小部件。

_Widget 接口

该接口用于定义一些设置方法,通过这些方法可以利用小部件管理器等类来统一管理小部件。

<!DOCTYPE html>
<html>
<head>
	<link rel="stylesheet" href="dojo/dijit/themes/claro/claro.css">
	<script>dojoConfig = { parseOnLoad: false }</script>
	<script src='dojo/dojo/dojo.js'></script>
	<script>
	    require([
            "dojo/_base/declare", "dojo/parser",
            "dijit/_WidgetBase", "dijit/_TemplatedMixin", "dojo/domReady!"
	    ], function (declare, parser, _WidgetBase, _TemplatedMixin) {
	        var MyButton = declare("MyButton", [_WidgetBase, _TemplatedMixin], {
	            templateString:
                    "<button data-dojo-attach-point='containerNode' data-dojo-attach-event='onclick: onClick'></button>",
	            onClick: function (evt) {
	                alert("Awesome!!");
	            }
	        });
	        parser.parse();
	    });
	</script>
</head>
<body class="claro">
    <button data-dojo-type="MyButton">press me</button>
</body>
</html>

8、可移动小部件

  • dojo/dnd/Moveable 移动组件
  • dojo/dom 文档组件
  • dojo/dom-style 样式组件
<!DOCTYPE html>
<html>
<head>
	<link rel="stylesheet" href="dojo/dijit/themes/claro/claro.css">
	<style type="text/css">
		#dndOne {
		  width: 100px;
		  height: 100px;
		  border: 1px solid #000;
		  background: red;
		}
		#dndArea {
		  height: 200px;
		  border: 1px solid #000;
		}
	    .auto-style1 {
            width: 140px;
        }
	    #close {
            height: 13px;
        }
	</style>
	<script>dojoConfig = { async: true, parseOnLoad: false }</script>
	<script src='dojo/dojo/dojo.js'></script>
	<script>
	    require(["dojo/dnd/Moveable", "dojo/dom", "dojo/on", "dojo/dom-style", "dojo/domReady!"],
        function (Moveable, dom, on, domStyle) {
            on(dom.byId("doIt"), "click", function () {
                var dnd = new Moveable(dom.byId("dndOne"));
            });
            on(dom.byId("close"), "click", function () {
                domStyle.set(dom.byId("dndOne"), "display", "none");
            });
            on(dom.byId("btxs"), "click", function () {
                domStyle.set(dom.byId("dndOne"), "display", "block");
            });
        });
	</script>
</head>
<body class="claro">
    <div id="dndArea">
	  	<div id="dndOne" style="width:200px; height:200px">   	
			<table style="background-color:black; align-content:flex-start;width:100%; height:30px">
				<tr style="vertical-align: top; color:white">
					<td class="auto-style1" >标题</td>
					<td><button id="close" style="height:30px" type="button">关闭</button></td>
				</tr>
			</table>
			<div style="height:150px" data-dojo-attach-point="containerNode"></div>
	  	</div>
	</div>
	<p><button id="doIt" type="button">拖动</button></p>
    <p><button id="btxs" type="button">显示</button></p>
</body>
</html>

9、模型与代码分离式小部件

<!DOCTYPE html>
<html>
<head>

    <link rel="stylesheet" href="dojo/dijit/themes/claro/claro.css">

    <script>dojoConfig = { parseOnLoad: false }</script>
    <script src='dojo/dojo/dojo.js'></script>

    <script>
        require([
            "test/js0310", "dojo/parser", "dojo/_base/window", "dojo/domReady!"
        ], function (testst, parser, win) {
            parser.parse();
            var mm = new testst();
            mm.placeAt(win.body());
            // mm.onClick();
        });
    </script>
</head>
<body class="claro">

</body>
</html>
## test/js0310.js

define(["dojo/_base/declare", "dijit/_WidgetBase", "dijit/_TemplatedMixin", "dojo/text!./031001.html", "dojo/dom"], function (declare, _WidgetBase, _TemplatedMixin, temstring, dom) {
    return declare([_WidgetBase, _TemplatedMixin], {
        templateString:
           temstring,
        onClick: function (evt) {
            var t = dom.byId("Text1");
            alert(t.value);
        }
    });
});
## 031001.html

<div>
    姓名:<input id="Text1" type="text" />
    <button data-dojo-attach-point='containerNode' data-dojo-attach-event='onclick: onClick'>确定</button>
</div>
## 0504343.html

<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="dojo/dijit/themes/claro/claro.css">
    <script>dojoConfig = { parseOnLoad: false }</script>
    <script src='dojo/dojo/dojo.js'></script>
    <script>
        require([
            "test/testst", "dojo/parser","dojo/_base/window",
            "dojo/domReady!"
        ], function (testst, parser, win) {
            parser.parse();
            var mm = new testst();
            mm.placeAt(win.body());
           // mm.onClick();
        });
    </script>
</head>
<body class="claro">

</body>
</html>
## testst.js

define(["dojo/_base/declare","dijit/_WidgetBase", "dijit/_TemplatedMixin",  "dojo/text!./0401.html","dojo/dom"], function (declare, _WidgetBase, _TemplatedMixin,temstring,dom) {
    return declare([_WidgetBase, _TemplatedMixin], {
        templateString:
           temstring,
        onClick: function (evt) {
            var t = dom.byId("Text1");
            alert(t.value);
        }
    });
});
## 0401.html

<div>
    姓名:<input id="Text1" type="text" />
    <button data-dojo-attach-point='containerNode' data-dojo-attach-event='onclick: onClick'>确定</button>
</div>

10、动画控制

动画类库 dojo/_base/fx

动画类库dojo/_base/fx 主要方法:

FadeIn()
  • FadeIn(dom节点对象)
FadeOut()
  • FadeOut(dom节点对象)
AnimateProperty()
AnimateProperty()属性
  • Node:DOM 节点的 ID
  • Properties:属性
  • Duration:动画时间
  • Rate:时间类型
  • Easing:指定动画缓和曲线函数
AnimateProperty() 事件处理函数
  • Play() 动画播放
  • Pause() 动画暂停
  • Status() 返回动画当前状态
  • Stop(gotoEnd) 停止播放,gotoEnd为true时候,当前位置位置为1%
<!DOCTYPE html>
<html>
<head>
	<link rel="stylesheet" href="dojo/dijit/themes/claro/claro.css">
	<style type="text/css">
		#dndOne {
		  width: 100px;
		  height: 100px;
		  border: 1px solid #000;
		  background: red;
		}
		#dndArea {
		  height: 200px;
		  border: 1px solid #000;
		}
	    .auto-style1 {
            width: 140px;
        }
	    #close {
            height: 13px;
        }
	</style>
	<script>dojoConfig = { async: true, parseOnLoad: false }</script>
	<script src='dojo/dojo/dojo.js'></script>
	<script>
	    require(["dojo/_base/fx", "dojo/dnd/Moveable", "dojo/dom", "dojo/on", "dojo/dom-style", "dojo/domReady!"],

        function (fx, Moveable, dom, on, domStyle) {
            //拖动
            on(dom.byId("doIt"), "click", function () {
                var dnd = new Moveable(dom.byId("dndOne"));
            });
            //关闭
            on(dom.byId("close"), "click", function () {
                domStyle.set(dom.byId("dndOne"), "display", "none");
            });
            //隐藏
            on(dom.byId("btyc"), "click", function () {
                var fadeArgs = {
                    node: dom.byId("dndOne")
                };
                fx.fadeOut(fadeArgs).play();
            });
            
            on(dom.byId("btxs"), "click", function () {           
               var fadeArgs = {
                   node: dom.byId("dndOne")
               };
               fx.fadeIn(fadeArgs).play();
            });
        });
	</script>
</head>
<body class="claro">
    <div id="dndArea">
	  	<div id="dndOne" style="width:200px; height:200px">   	
			<table style="background-color:black; align-content:flex-start;width:100%; height:30px">
				<tr style="vertical-align: top; color:white">
					<td class="auto-style1" >标题</td>
					<td><button id="close" style="height:30px" type="button">关闭</button></td>
				</tr>
			</table>
			<div id="divct"  style="height:150px" data-dojo-attach-point="containerNode"></div>
	  	</div>
	</div>
	<p><button id="doIt" type="button">拖动</button></p>
    <p><button id="btyc" type="button">隐藏</button></p>
    <p><button id="btxs" type="button">显示</button></p>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
	<link rel="stylesheet" href="dojo/dijit/themes/claro/claro.css">
	<style type="text/css">
		#statusCode {
		    padding: 5px;
		    border: 1px solid #000;
		    background: red;
		    text-align: center;
		    width: 100px;
		}
	</style>
	<script>dojoConfig = { parseOnLoad: true }</script>
	<script src='dojo/dojo/dojo.js'></script>
	<script>
	    require(["dojo/dom", "dojo/_base/fx"], function (dom, fx) {
	        statusOk = function () {
	            fx.animateProperty({
	                node: dom.byId("statusCode"), duration: 500,
	                properties: {
	                    backgroundColor: { start: "red", end: "green" },
	                    color: { start: "black", end: "white" },
	                },
	                onEnd: function () {
	                    dom.byId("statusCode").innerHTML = "Granted";
	                }
	            }).play();
	        };
	    });
	</script>
</head>
<body class="claro">
    <p><button onclick="statusOk();">确定</button></p>
	<div id="statusCode">颜色变化</div>
</body>
</html>

11、订阅、发布模式的事件处理机制

订阅发布模式

订阅/发布模式可以说是一个预定系统,用户先预定自己感兴趣的主题,当此类主题发布时,将在第一时间得到通知。在订阅/发布模式下,预订的时候并不确定主题是否已经存在,以后是否会发布,只是在主题发布后,会立即得到通知。在 DOJO 中,跟订阅 /发布有关的函数位于 dojo/topic 模块中,有两个:subscribe 和 publish。

Subscribe

Subscribe函数用来订阅某一主题,将接收两个参数,1.主题名字,为一个字符串,必须能够唯一标示的主题 2.参数的回调函数。 Subscribe返回一个句柄,该句柄的remove方法用于取消订阅。

Publish

Publish用于发布某个主题,将接收多个参数,1.为发布信息的名字,其他参数为传递给订阅回调函数的参数。

<!DOCTYPE html>
<html >
<head>
	<link rel="stylesheet" href="dojo/dijit/themes/claro/claro.css">
	<script>dojoConfig = { async: true, parseOnLoad: false }</script>
	<script src='dojo/dojo/dojo.js'></script>
	<script>
	    require(["dojo/topic", "dojo/dom", "dojo/on", "dojo/domReady!"],
        function (topic, dom, on) {

            var handle = topic.subscribe("some/topic", function (e) {
                dom.byId("output").innerHTML = "邮件已经发送给: " + e.msg;
                handle.remove();
            });

            on(dom.byId("publish"), "click", function () {
                topic.publish("some/topic", { msg: "小王" });
            });

        });
	</script>
</head>
<body class="claro">
    <button type="button" id="publish">请单击</button>
    <div id="output">输出信息</div>
</body>
</html>

12、Calendar 组件

<!DOCTYPE html>
<html>
<head>
	<link rel="stylesheet" href="dojo/dijit/themes/claro/claro.css">
	<script>dojoConfig = { parseOnLoad: true }</script>
	<script src='dojo/dojo/dojo.js'></script>
	<script>
	    require(["dojo/ready", "dojox/calendar/Calendar"]);
	</script>
</head>
<body class="claro">
    <style type="text/css">
  		.dojoxCalendar{ font-size: 12px; font-family:Myriad,Helvetica,Tahoma,Arial,clean,sans-serif; }
	</style>

	<div data-dojo-type="dojox/calendar/Calendar"
	     data-dojo-props="dateInterval:'day'"
	     style="position:relative;width:600px;height:600px">
</div>
</body>
</html>

13、Dojo 的 Ajax 与 WebService通信

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
    <link rel="stylesheet" href="dojo/dijit/themes/claro/claro.css">
	<script>dojoConfig = { parseOnLoad: true }</script>
	<script src='dojo/dojo/dojo.js'></script>
    <script type="text/javascript">
         function init() {
             // 将待传入的Web方法参数转换为json格式
             var myname = dojo.toJson({ "name": "百度传课" });
             // 构造dojo.xhrPost方法的参数
             var xhrArgs = {
                 // web service的地址,具体到方法名称,不能在此接参数
                 url: "http://localhost:21062/WebService1.asmx/Hello",
                 // 让web service以json方式对待传入的参数
                 handleAs: "json",
                 headers: { "Content-Type": "application/json" },//或者contentType: "application/json",               
                 // 如果web方法没有参数,则下一行可不写(写了也没事儿)
               	 // postData: myname,
                 // 调用成功时的处理函数
                 load: loadHandler,
                 // 调用失败时的处理函数
                 error: errorHandler
             };
             // 以POST方式调用web service
             dojo.xhrPost(xhrArgs);
         }

         function loadHandler(response) {
             // 直接取出返回的数据,如SayHello方法返回的结果:Hello yelloweast
             var p = response.d;
             alert("姓名:" + p.Name+",年龄:"+p.Age);
             // 取出返回的对象的属性,如Hello方法返回的结果:Yellow East
             // alert(response.d.Name);
         }

         function errorHandler(error) {
             alert(error);
         }

         dojo.addOnLoad(init);
  </script>
</head>
<body>

</body>
</html>

14、C# .Net Core 示例代码

## WebService.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;

/// <summary>
/// WebService1 的摘要说明
/// </summary>
[WebService(Namespace = "http://weibo.com/yelloweast")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]//表示复合wsi规范
[System.ComponentModel.ToolboxItem(false)]//表示工具箱的特性
[System.Web.Script.Services.ScriptService]
// 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消注释以下行

public class WebService1 : System.Web.Services.WebService {

    [WebMethod]
    public string SayHello(string name)
    {
        return "你好 " + name;
    }

    [WebMethod]
    public People Hello()
    {
        People p = new People();
        p.Name = "小王";
        p.Age = 27;
        return p;
    }

    public class People
    {
        private string name;
        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        private int age;
        public int Age
        {
            get { return age; }
            set { age = value; }
        }
    }
}
## Web.config

<?xml version="1.0" encoding="utf-8"?>

<!--
  有关如何配置 ASP.NET 应用程序的详细信息,请访问
  http://go.microsoft.com/fwlink/?LinkId=169433
  -->

<configuration>
    <system.web>
      <compilation debug="true" strict="false" explicit="true" targetFramework="4.5" />
      <httpRuntime targetFramework="4.5" />
    </system.web>
</configuration>
## Web.Debug.config

<?xml version="1.0" encoding="utf-8"?>

<!-- 有关使用 web.config 转换的详细信息,请访问 http://go.microsoft.com/fwlink/?LinkId=125889 -->

<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
  <!--
    在下例中,“SetAttributes”转换将更改 
    “connectionString”的值,以仅在“Match”定位器 
    找到值为“MyDB”的特性“name”时使用“ReleaseSQLServer”。
    
    <connectionStrings>
      <add name="MyDB" 
        connectionString="Data Source=ReleaseSQLServer;Initial Catalog=MyReleaseDB;Integrated Security=True" 
        xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
    </connectionStrings>
  -->
  <system.web>
    <compilation xdt:Transform="RemoveAttributes(debug)" />
    <!--
      
      在下例中,“Replace”转换将替换 
      web.config 文件的整个 <customErrors> 节。
      请注意,由于 
      在 <system.web> 节点下仅有一个 customErrors 节,因此不需要使用“xdt:Locator”特性。
      
      <customErrors defaultRedirect="GenericError.htm"
        mode="RemoteOnly" xdt:Transform="Replace">
        <error statusCode="500" redirect="InternalError.htm"/>
      </customErrors>
    -->
  </system.web>
</configuration>
<%@ WebService Language="C#" CodeBehind="~/App_Code/WebService1.cs" Class="WebService1" %>
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 书香水墨 设计师:CSDN官方博客 返回首页