自从我上一个ajax项目完成以来,我就一直在考虑ajax的response输出格式有没有比较理想的方式。一旦你成功的发送一个ajax请求,
server端应该给你什么样的response,一个xml文档,一段html代码还是会被转换为javascript 对象的 json,或者其它的什么东西?
在这篇文章里我会利用实例讨论这三种格式,并问你在你的ajax应用中使用的是哪种格式。
当你为你的ajax应用接收到一些数据时,你应该启动一段脚本把这些数据合并到你的html页面中去,当然脚本的形式主要依赖于你接收
到的数据的形式,你是会在xml文档中查找特定的节点并把它的文本拷贝到你的html中去还是直接把接收到的html片段加到页面中去呢?
在我上一个ajax项目中我接受到数据一部分是xml文档的形格式,一部分是html片段的形式,这些数据形式需要不同的脚本来写入到页面中去。
这两种数据形式,以及脚本样式都有各自的优点和缺点。
在我把项目做完后,我深入地研究了由Douglas Crockford 发明并在大多数的yahoo服务上被选作默认的输出格式的 JavaScript Object Notation,
尽管 我还从没用过,但我想我喜欢它。
我留下一个疑问:哪一种格式是最好的,你认为哪种格式是最好的或者在实际的ajax环境中至少是最有用的?
例子
我们以一个ajax驱动的在线书店为例子来说明一下这3种格式。我们向书店询问他们书店里的javascript 书籍,非常巧合的是我书桌上就放这着这样的3本
javascript书。一个ajax请求返回3个结果,你必须要把这些结果合并到你的html页面中去。
我会以这三种格式为例子,并附以简单的脚本 在<div id="writeroot"> 中来展示结果。
XML 文档
第一个也是最明显的输出格式的选择是xml文档格式。XMLHTTP 对象最初的想法是引入xml文档,因此毫无疑问的更多的人把注意力集中到xml身上,它也被
当成是默认的输出格式。
例子
服务器返回如下的xml文档
<books>
<book>
<title>JavaScript, the Definitive Guide</title>
<publisher>O'Reilly</publisher>
<author>David Flanagan</author>
<cover src="/images/cover_defguide.jpg" />
<blurb>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</blurb>
</book>
<book>
<title>DOM Scripting</title>
<publisher>Friends of Ed</publisher>
<author>Jeremy Keith</author>
<cover src="/images/cover_domscripting.jpg" />
<blurb>Praesent et diam a ligula facilisis venenatis.</blurb>
</book>
<book>
<title>DHTML Utopia: Modern Web Design using JavaScript & DOM</title>
<publisher>Sitepoint</publisher>
<author>Stuart Langridge</author>
<cover src="/images/cover_utopia.jpg" />
<blurb>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</blurb>
</book>
</books>
我们需要如下的这段脚本在我们的<div>中显示结果
function setDataXML(req)
{
var books = req.responseXML.getElementsByTagName('book');
for (var i=0;i<books.length;i++)
{
var x = document.createElement('div');
x.className = 'book';
var y = document.createElement('h3');
y.appendChild(document.createTextNode(getNodeValue(books[i],'title')));
x.appendChild(y);
var z = document.createElement('p');
z.className = 'moreInfo';
z.appendChild(document.createTextNode('By ' + getNodeValue(books[i],'author') + ', ' + getNodeValue(books[i],'publisher')));
x.appendChild(z);
var a = document.createElement('img');
a.src = books[i].getElementsByTagName('cover')[0].getAttribute('src');
x.appendChild(a);
var b = document.createElement('p');
b.appendChild(document.createTextNode(getNodeValue(books[i],'blurb')));
x.appendChild(b);
document.getElementById('writeroot').appendChild(x);
}
}
function getNodeValue(obj,tag)
{
return obj.getElementsByTagName(tag)[0].firstChild.nodeValue;
}
你可以看到,这是相当长的代码。尽管W3C DOM规范允许我们访问服务器返回的xml文档以及这些数据需要展现在其中的html文档,但他并未给我们一种优雅简洁的
准确抽取我们需要的数据的方式,我们必须反复的处理xml文档。
现在XSLT应该出现了,因为这是一种可以把xml文档转换为另一种xml格式的手段,并且XHTML也是XML,我们可以也可以用它来创建web页面。我是从1999年开始研究
XSL(T)的,在我开始写一个可以执行的例子之前无疑的需要解决很多小的兼容性问题,我会把XSLT留在以后的时间来说明。
优点
xml最大的优点是这是让其他人最容易阅读的格式。
第二个优点是XML已经出现了相当长的时间了,许多开发者已经习惯它了。假设有人说“我想让服务端脚本返回一个xml文档”不会造成疑惑,而若是说“我想让服务端
脚本返回一个JSON对象”则可能会引起疑惑。
缺点
把数据插入html页面的javascript脚本非常的冗长,我写了一个比较方便的函数getNodeValue()来减少这种冗长和令人讨厌的脚本,该函数作用是从XML标记中读取
文本。尽管如此这些脚本看上去仍然不漂亮。
HTML片段
第二种方式,可能是最有趣的,输出html片段的方式。记住我称它为片段,因为我们并不会接收一个完整的html页面,而是一段要插入我们的<div>标记的html代码。
例子
服务端会返回如下的html片段
<div class="book">
<h3>JavaScript, the Definitive Guide</h3>
<p class="moreInfo">By David Flanagan, O'Reilly</p>
<img src="/images/cover_defguide.jpg" />
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</p>
</div>
<div class="book">
<h3>DOM Scripting</h3>
<p class="moreInfo">By Jeremy Keith, Friends of Ed</p>
<img src="/images/cover_domscripting.jpg" />
<p>Praesent et diam a ligula facilisis venenatis.</p>
</div>
<div class="book">
<h3>HTML Utopia: Modern Web Design using JavaScript & DOM</h3>
<p class="moreInfo">By Stuart Langridge, Sitepoint</p>
<img src="/images/cover_utopia.jpg" />
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.</p>
</div>
与之相应的脚本非常的简单,仅仅是把responseText 赋给你会读取的那个对象的innerHTML 属性。
function setDataHTML(req)
{
document.getElementById('writeroot').innerHTML = req.responseText;
}
优点
脚本的简单是这种方式最大的优点。
另外,这种格式提供了有趣的(this format offers interesting accessibility options).我们可以写这样一段脚本,该脚本能创建一个完整的可访问的能在任何
设备上展现的html页面。如果这个请求恰巧是由ajax脚本发送的,服务端的脚本就会抛弃掉出了查询结果之外的所有HTML,或者AJAX脚本本身查询结果。
当然了,使用XML或JSON时也很可能创建具有相似的可访问性特征的脚本,但是HTML片段格式是最简单的。
缺点
如果HTML片段包含form,或者要接受的HTML元素是一个form,这种方法在浏览器中可能会导致可怕的错误。
另外,HTML片段可能会变得很复杂。上面的例子并不复杂,但是一旦你想要使用高级的会使用更多不严格要求的元素的CSS技术,这些片段可能会包含额外的<span>元素
或者任何你需要的元素。这样生成这些HTML的服务段脚本可能会变得非常复杂。
JSON
第三种方式是JSON,javascript 对象符号,我个人把它读成“jason”,就想另一个古代的希腊英雄来到了当代的javascript开发之中(请记住Ajax之父Telamon
accompanied Jason as an Argonaut,Jason 更加古老,基本上比Ajax也更加成功)。
大致的思想是传输一段能被解释成JavaScript对象的文本(实际上是String)。一旦就收到了该文本,你就可以使用javascrpt的eval()函数把这段String转换成真正的
javascript对象,接着你就能读取该对象。
例子
server 端返回如下的JSON 字符串:
{"books":[{"book":
{
"title":"JavaScript, the Definitive Guide",
"publisher":"O'Reilly",
"author":"David Flanagan",
"cover":"/images/cover_defguide.jpg",
"blurb":"Lorem ipsum dolor sit amet, consectetuer adipiscing elit."
}
},
{"book":
{
"title":"DOM Scripting",
"publisher":"Friends of Ed",
"author":"Jeremy Keith",
"cover":"/images/cover_domscripting.jpg",
"blurb":"Praesent et diam a ligula facilisis venenatis."
}
},
{"book":
{
"title":"DHTML Utopia: Modern Web Design using JavaScript & DOM",
"publisher":"Sitepoint",
"author":"Stuart Langridge",
"cover":"/images/cover_utopia.jpg",
"blurb":"Lorem ipsum dolor sit amet, consectetuer adipiscing elit."
}
}
]}
下面的这段脚本看上去与处理XML的脚本很像。它作一样的事情,它只是从另一种格式中读取数据。在这里很自然的也会想到XSLT。
function setDataJSON(req)
{
var data = eval('(' + req.responseText + ')');
for (var i=0;i<data.books.length;i++)
{
var x = document.createElement('div');
x.className = 'book';
var y = document.createElement('h3');
y.appendChild(document.createTextNode(data.books[i].book.title));
x.appendChild(y);
var z = document.createElement('p');
z.className = 'moreInfo';
z.appendChild(document.createTextNode('By ' + data.books[i].book.author + ', ' + data.books[i].book.publisher));
x.appendChild(z);
var a = document.createElement('img');
a.src = data.books[i].book.cover;
x.appendChild(a);
var b = document.createElement('p');
b.appendChild(document.createTextNode(data.books[i].book.blurb));
x.appendChild(b);
document.getElementById('writeroot').appendChild(x);
}
}
优点
最重要的优点是JSON环境下如果你用<script>标签倒入了JSON文件,javascript代码不需要改变的原则。请看
<a href=http://simon.incutio.com/archive/2005/12/16/json>Simon Willison's example</a> 中血淋淋的事实。
javascript 不允许你访问来自于另一个服务上的文档(可能是XML或者HTML)。然而如果你用<script>标签导入了一个JSON文件来解决这个问题,这样任何
JSON数据可以导入到任何web站点上。这到底是好事还是坏事取决于你的业务目标,但是现在这是允许你无限制访问数据的唯一的数据格式。
第二个优点是取JSON数据的脚本跟取XML数据的脚本相比一是稍微简单些,另外与其他的javascript略微一致些。
缺点
JSON最大的缺点是这种格式很难让人读懂,并且每一个逗号,引号和括号都应该正确的出现在恰当的位置。以下这点对XML来说也是一样的,那就是JSON
看上去复杂的语法,就像位于数据片段结尾的 }}]},可能会使那些新手害怕,并且导致调试的过程比较复杂。
你的选择?
现在有3种取得AJAX数据的格式。尽管我很希望我能说他们中的一个是最好的,我认为选取恰当的格式取决于具体的环境,而不应当是理论的思考。
尽管如此,我们还是take a stab at 找一下最好的格式。我有以下四个问题:
1.你能想出另一种输出格式吗?
2.你在实际的,商业的AJAX应用中使用哪种输出格式?(例子和个人偏好的不算)
3.你会在未来转换到另一种输出格式吗,如果是会是哪种以及原因?
4.你能想出这三种格式的其他的优点或缺点吗?
我自己的答案是:
1.不能。
2.主要是XML文档,少部分是HTML片段。
3.我会认真地学习JSON并可能想在一个访问无限制的应用中使用它。尽管我认为目前XML仍就是主要的格式,主要是因为人们已经习惯于它。
4.我已经写了我能想到的所有的优点和缺点。
<!-- 日期 2006.03.27 19:00 英文原址 http://www.quirksmode.org/blog/archives/2005/12/the_ajax_respon.html -->