web前端之精通dojo二:连接外部服务
前面我们看到了dijit改善用户到浏览器的体验。现在我们将研究的重点放到浏览器这个过程中。Ajax,即异步JavaScript和XML,就是一种浏览器与服务器交互技术,它避免了表单提交和静态界面重绘带来的繁琐、重复的工作,而且它还改善了界面,增强用户体验。
Dojo远程脚本:
XMLHttpRequest(XHR)是ajax中主要的知识点,下面是其诸多奇怪特点中的几个:
语法令人陌生:许多程序员只是简单地复制和粘贴某些XHR源代码的片段,但是根本不知道这些代码是用来干嘛的。这样增加了程序调试的难度。
对内容类型的处理能力差。尽管人们认为XHR能够非常流畅地表达XML,然而当人们从服务器获取XML时,从XHR那里得到一个令人费解的消息--“无效XML”
对构造参数字符毫无帮助:程序员不得不亲手完成所有的URL编码,或者根本不对URL进行编码
…
但是dojo会让你从中解脱出来:
dojo的远程脚本工具能够让一个客户端脚本在不重复装载页面的情况下与服务器通信。远程脚本的XHR易用性和伪XHR API扩展了应用程序的能力,使得应用程序能够访问用户自己的服务之外的服务。而且dojo在完成这一切的同时并不完全依赖JavaScript。dojo和dijit提供了建立在XHR之上的控制和数据转换服务,让人们能够更好地使用XHR,这里我们主要使用dojo的三种技术:
dojo.data是一种类似于JDBC或ODBC的API规范。dojo.data驱动程序中实现了这个规范,并且负责响应那些来自数据小部件或JavaScript代码的请求。一般来说,每个驱动程序负责一种不同的数据提供者格式,例如JSON或XML。
dojo.io.script方法在其他领域访问JSONP服务。XHR必须准守同源规则,即只能调用那些与外部页面属于同一台服务器的服务。JSONP通过使用script标签巧妙地绕过这一限制。
dojo.xhrGet、dojo.xhrPost、dojo.rawXhrPost、dojo.xhrPut、dojo.rawXhrPut、dojo.xhrDelete以及dojo.xhr方法是最底层的远程脚本服务。这些被统计为dojo.xhr*的方法并不提供dojo.data提供的公共API层和数据转换服务
调用XHR相关的JavaScript习惯用语:
字面量和散列:
字面量就是源代码中用于标识某个固定值的符号。因此在JavaScript中,“Foo”就是一个函数的字面量。1是一个数值字面量,而[1,2,3]是一个数组字面量。字面量是某个特定JavaScript类型的基本数据单元。
散列(hash)就是名称-值对的集合,这些对被称为属性。每个属性名称只能在一个散列中出现一次属性就是具有两列的数据表的行,其中属性名称就是主键。
在JavaScript中,任何Object类型的实例都是属性的集合。尽管,我们知道对象的使用远比属性的简单集合多得多,但是有时人们所需要的仅仅只是把一些属行绑定在同一个地方而已。当某个对象这么使用时,我们称之为散列。
{
"a":1
,"b":2
,"c":3
}
注意:注意永远都不要以逗号作为最后一个属性-值对的结尾。目前只有Firefox可以忽略这一点,而其他浏览器却没有,所以使用散列的时候还是谨慎点。
var durger={patties:12,tyep:"gard",bun:"wheat"};
console.dir(durger);
console.dir方法将散列属性打印到日志中。该方法在打印对象、数组以及各种各样的复杂数据结构时同样便利。console.debug比console.dir稍微弱一点,它打印字符串、数字和其他基本数据类型。console.log和coosole.error的功能和console.debug相同,但是它们打印的内容在控制台会以不同的消息级别和图标予以显示。
散列字面量也有一种非常方便的句法快捷方式。
var durger={};
durger.patties=12;
durger.tyep="gard";
durger.bun="wheat";
console.dir(durger);
结果和上面完全一致
以dojo.io.script.get为例:
dojo.io.script.get({
//Yahoo Search的URL
url:"http://search.yahooapis.com/WebSearchService/V1/webSearch",
//向搜索服务发送的参数:
content:{
appid:"DEMO",
query:searchTerms,
output:"json",
},
//如果响应时间超过10000ms(10s),退出并抛出错误
timeout:10000,
//Yahoo API要求你将回调函数的名字放在“callback”参数中
callbackParamName:"callback"
//完整的调用还包括载入和错误处理参数等
});
所有的数据都包含url、content等属性被传递。虽然这种方式可以使用独立的基础类型参数来模拟,但是使用散列字面量来完成这一操作有以下几点优势:
1.散列字面量比一组参数具有更强的描述性。比如用dojo.io.script.get(1,”abc”,…)比起上面的dojo.io.script.get,我们不得不查询这个“1”到底代表什么。
2.可以再散列字面量中对属性进行重新排序,或者跳过某个属性,而这并不会造成任何影响
3.假设使用同样的参数多次调用某个方法构建一个散列,然后将其反复传递给该方法。要比每次都传递参数更有效。
函数字面量:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>函数字面量</title>
<script type="text/javascript" src="../../../dojoroot/dojo/dojo.js" djConfig="parseOnLoad:true">
</script>
<style type="text/css">
@import "../../../dojoroot/dijit/themes/tundra/tundra.css";
@import "../../../dojoroot/dojo/resources/dojo.css";
</style>
<script type="text/javascript">
var listNode=document.getElementById("listOfUrls");
var urls=[
{url:"http://www.baidu.com",title:"Baidu"},
{url:"http://www.google.com",title:"google"},
{url:"http://www.qq.com",title:"qq"}
];
dojo.forEach(urls,function(oneResult){
var listItem=document.createElement("li");
listItem.innerHTML=dojo.string.substitute("<a href='${url}'>${title}</a>",oneResult);
listNode.appendChild(listItem);
});
</script>
</head>
<body>
<div id="listOfUrls">
</div>
</body>
</html>
dojo.forEach类似于foreach。
使用$(…)占位符,$(url)被oneResult.url替换。
使用dojo.data和dojo.grid.Grid的Wish List:
{
"identifier":"wishId",
"lable":"description",
"item":[
{
"wishId":1,
"description":"Don Pepin Gar",
"size":"7-50",
"origin":"Nica",
"wrapper":"Corojo",
"shape":"Staight"
},
{
"wishId":11,
"description":"Don Pepin Gar1",
"size":"7-501",
"origin":"Nica1",
"wrapper":"Corojo1",
"shape":"Staight1"
},
{
"wishId":12,
"description":"Don Pepin Gar2",
"size":"7-502",
"origin":"Nica2",
"wrapper":"Corojo2",
"shape":"Staight2"
}
]
}
现在我们将这个数组传入dojo.data的驱动dojo.data.ItemFileReadStore中。该驱动要求传入的JSON数据要具备如下的特定格式:identifier是包含某个项的ID的域;item则是数据本身,也就是一个散列构成的数组。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>使用dojo.data和dojo.grid.Grid的Wish List</title>
<script type="text/javascript" src="../../../dojoroot/dojo/dojo.js" djConfig="parseOnLoad:true">
</script>
<style type="text/css">
@import "../../../dojoroot/dijit/themes/tundra/tundra.css";
@import "../../../dojoroot/dojo/resources/dojo.css";
@import "../../../dojoroot/dojox/grid/_grid/tundarGrid.css";
</style>
<script type="text/javascript">
dojo.require("dojo.parser");
dojo.require("dojo.data.ItemFileReadStore");
dojo.require("dojox.grid.Grid");
</script>
<style type="text/css">
#grid{
border: 1px solid #333;
width: 550px;
margin: 10px;
height: 200px;
font-size: 0.9em;
font-family: Geneva, Arial, Helvetica,sans-serif;
}
</style>
</head>
<body class="tundra">
<h1>Justa Cigar Corporation</h1>
<h3>"Sometimes a cigar is a Justa Cigar!"</h3>
<div dojoType="dojo.data.ItemFileReadStore" jsId="wishStore" url="1.json"></div>
<table id="grid" dojoType="dojox.grid.Grid" store="wishStore" query="{wishId:'*'}" clientSort="true">
<thead>
<tr>
<th field="description">description</th>
<th field="size">size</th>
<th field="origin">origin</th>
<th field="wrapper">wrapper</th>
<th field="shape">shape</th>
</tr>
</thead>
</table>
</body>
</html>