在本文中将给出一个例子来介绍使用AJAX
技术从服务端获得数据的三种方法。这个例子很简单,就是两个选择框(html
中的<select>
标签),通过选中第一个select
的某一项后,会从服务端得到一些数据,并加载到第2
个select
中。
方法一、从服务端获得XML格式的数据
从服务端获得数据的最容易想到的方法就是在服务端反加一定格式的数据,一般是XML格式,然后在服务端使用XMLDocument或其他技术来读取这些数据,并生成<select>标签中选项的格式文本(<option>标签)。下面的addOptions函数是这个例子的核心函数,它负责根据从服务端获得的数据生成<select>标签中的<option>标签。在这里所使用的方法是利用了<select>标签的innerHTML属性(仅限于firefox),如果是IE,要使用outerHTML属性(IE中<select>标签的innerHTML属性有一些小bug,读者可以试着在IE中使用innerHTML属性,看看会发生什么情况)。addOptions方法的实现代码如下:
<!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->//select表示<select>对象,xml表示XMLDocument对象
functionaddOptions(select,xml)
{
if(select)
{
varoptions="";
for(vari=0;i<xml.childNodes[0].childNodes.length;i++)
{
if(xml.childNodes[0].childNodes[i].nodeName=="list")
{
vars="";
if(isIE())
s=xml.childNodes[0].childNodes[i].text;
else
s=xml.childNodes[0].childNodes[i].textContent
options+="<optionvalue='"+s+"'>";
options+=s;
options+="</option>"
}
}
varid=select.id;
if(isIE())
select.outerHTML="<SELECTid='"+id+"'onchange='onChange(this)'>"+options+"</SELECT>";
else
select.innerHTML=options;
}
}
onReadState函数将在XMLHttpRequest对象的异步访问服务端时调用。当readyState为4时表示成功从服务端返回XML数据。这个函数的实现代码如下:
<!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->//myRequest表示XMLHttpRequest对象,selectId表示<select>标签的id属性值
functiononReadyState(myRequest,selectId)
{
if(myRequest.readyState==4)//4表示成功获得相应信息
{
try
{
varxml=myRequest.responseXML;//获得XMLDocument对象
varkind=document.getElementById(selectId);//获得<select>对象
addOptions(kind,xml);//向<select>标签中加入<option>标签
}
catch(e)
{
alert("onReadyState:"+e);
}
}
}
getData函数负责向服务端发送请求,并设置异步事件。实现代码如下:
<!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->functiongetData(url,selectId)
{
varmyRequest=getXMLHTTPRequest();//获得一个XMLHttpRequest对象
if(myRequest)
{
myRequest.onreadystatechange=function()//接收获得数据状态的事件函数
{
onReadyState(myRequest,selectId);
}
try
{
myRequest.open("post",url,true);
}
catch(e)
{
alert(e);
}
try
{
myRequest.send("");
}
catch(e)
{
alert(e);
}
}
}
现在本例子的核心代码已经实现完成,下一步就是在html而加载时从服务端获得第1个<select>标签的数据,并将其加载到第1个<select>标签中。让我们先看一下这个静态的html代码。
<!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><!DOCTYPEHTMLPUBLIC"-//W3C//DTDHTML4.01Transitional//EN">
<html>
<head>
<title></title>
<metahttp-equiv="Content-Type"content="text/html;charset=UTF-8">
<scripttype="text/javascript"src="myscript.js">
</script>
</head>
<body>
<selectid="bigKind"onchange="onChange(this)">
</select>
<selectid="smallKind">
</select>
</body>
</html>
从上面代码可以看出,这两个<select>标签分别是bigKind和smallKind,里面并没有<option>标签,这是因为<option>标签要在javascript里动态加载。下面我们先来加载bigKind中的数据。
<!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->window.onload=onLoad
functiononLoad()
{
try
{
getData("../GetXML","bigKind");
}
catch(e)
{
alert("onLoad:"+e);
}
}
其中GetXML是一个Servlet程序(读者可以将其换成其他的服务端程序,如asp.net、php的)。下面是这个GetXML程序的实现代码:
<!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->packageservlet;
importjava.io.*;
importjavax.servlet.*;
importjavax.servlet.http.*;
importdatabase.MyData;
publicclassGetXMLextendsHttpServlet
{
protectedvoidprocessRequest(HttpServletRequestrequest,HttpServletResponseresponse)
throwsServletException,IOException
{
response.setContentType("application/xml;charset=UTF-8");
PrintWriterout=response.getWriter();
try
{
Strings=request.getParameter("kind");
out.println("<data>");
if(s==null)
{
for(Stringkey:MyData.data.keySet())
{
out.println("<list>"+key+"</list>");
}
}else
{
s=java.net.URLDecoder.decode(s,"UTF-8");
System.out.println(s);
java.util.List<String>smallKind=MyData.data.get(s);
if(smallKind!=null)
{
for(Stringkind:smallKind)
{
out.println("<list>"+kind+"</list>");
}
}
}
out.println("</data>");
}finally
{
out.close();
}
}
protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)
throwsServletException,IOException
{
processRequest(request,response);
}
protectedvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)
throwsServletException,IOException
{
processRequest(request,response);
}
publicStringgetServletInfo()
{
return"Shortdescription";
}
}
不管读者会不会java和servlet,从这个程序中的processRequest方法中都可以看出,首先会获得请求参数kind,如果这个参数不存在,则返回bigKind所需要的数据,以xml格式返回,类似于如下的格式:
<!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><data>
<list>data1</list>
<list>data2</list>
</data>
如果kind参数存在,则在MyData.data中查询第2个<select>标签(smallKind)所需要的数据。data是一个Map类型。为了方便起见,本例子并未使用数据库,而是在MyData类中定义了一个静态的Map类型变量。MyData的实现代码如下:
<!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->packagedatabase;
importjava.util.*;
publicclassMyData{
publicstaticMap<String,List<String>>data;
static{
data=newHashMap<String,List<String>>();
List<String>eProducts=newLinkedList<String>();
eProducts.add("手机");
eProducts.add("数码/IT");
eProducts.add("家电");
eProducts.add("电脑");
data.put("消费电子",eProducts);
List<String>goods=newLinkedList<String>();
goods.add("化妆");
goods.add("健康");
goods.add("玩具");
goods.add("办公/文体");
goods.add("童装童鞋");
goods.add("其他");
data.put("日用百货",goods);
List<String>books=newLinkedList<String>();
books.add("小说");
books.add("动漫");
books.add("经济");
books.add("法律");
books.add("计算机");
books.add("英语");
books.add("通讯");
books.add("其他");
data.put("图书",books);
}
}
其中data变量中的key值就是bigKind中的值,而每一个key对应的值(一个List<String>对象就是smallKind中值的列表)。下面我们来实现当第1个<select>标签bigKind变化时,更新smallKind标签。<select>的onchange事件函数的代码如下:
<!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->functiononChange(obj)
{
try
{
getData(encodeURI(encodeURI("../GetXML?kind="+obj.options[obj.selectedIndex].value)),"smallKind");
}
catch(e)
{
alert(e);
}
}
这个函数是<select>标签的onchange事件函数。obj表示<select>标签本身。这个函数中只有一条有实际意义的语句,也就是调用了getData方法,这个方法人在onLoad方法中调用getData时差不多,只是在传送url时使用了两个encodeURI方法。由于XMLHttpRequest方法以utf-8向服务端发送数据,因此,要使用两个encodeURI向服务端发送%xx形式的utf-8编码,然后在服务端进行解析。我们在GetXML中的processRequest方法中可以找到如下的一条语句:
<!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->s=java.net.URLDecoder.decode(s,"UTF-8");
就是进行解码操作。
注:如果在IE中,客户端可以不使用encodeURI对带中文的URL进行编码,服务端也不用解码。在服务端仍然可以正常显示中文。但在firefox中就必须要进行编码和解码。因此,要想跨浏览器,就需要使用本文所述的方法。
方法二、直接获得<option>...</option>内容的字符串
上面的获得数据的方法是从服务端获得了一个XML文档,并转换成XMLDocument对象,然后解析。这种方法虽然很好,但是操作XMLDocument对象还是有些麻烦,因此,我们可以在服务端直接反回<select>标签所需要的<option>标签字符串,然后将这些字符串传给<select>对象的innerHTML或outerHTML就可以了。服务端的代码和上面的实现代码类似,只需要将<data>去掉,然后将<list>改为<option>后,并使用如下的语句来设置ContentType:
response.setContentType("text/html;charset=UTF-8");
客户端可通过XMLHttpRequest对象的responseText属性获得这些含有<option>的文本,并将其赋给innerHTML或outerHTML属性。这种方法虽然很方便,但并不灵活。如果客户端不使用<select>标签,而是使用<table>或其他的标签显示数据,那么返回的这些数据就没什么用处了。而即方便,又灵活的应该是下面要介绍的方法。
方法三、从服务端返回javascript代码,在客户端使用eval函数执行
我们可以在服务端返回类似于如下的字符串:
var options = new Array();
options.push(‘data1’);
options.push(‘data2’);
然后使用eval函数执行上面的字符串,这样我们在javascript中就可以使用options数组了。我个人认为,使用数组要比使用XMLDocument更容易,代码量也更少。如果要返回更为复杂的数据,也可以使用javascript中的类或其他数据结构。根据上面的思想,新的processRequest方法的代码如下:
<!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->protectedvoidprocessRequest(HttpServletRequestrequest,HttpServletResponseresponse)
throwsServletException,IOException
{
response.setContentType("text/html;charset=UTF-8");
PrintWriterout=response.getWriter();
out.println("varoptions=newArray();");
try
{
Strings=request.getParameter("kind");
if(s==null)
{
for(Stringkey:MyData.data.keySet())
{
out.println("options.push('"+key+"');");
}
}else
{
s=java.net.URLDecoder.decode(s,"UTF-8");
System.out.println(s);
java.util.List<String>smallKind=MyData.data.get(s);
if(smallKind!=null)
{
for(Stringkind:smallKind)
{
out.println("options.push('"+kind+"');");
}
}
}
}finally
{
out.close();
}
}
客户端经过改进的addOptions函数如下:
<!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
-->//javascript表示从服务端返回的javascript代码字符串
functionaddOptions(select,javascript)
{
if(select)
{
if(select.id=="smallKind")
{
if(isIE())
select.options.length=0;
}
varmyOptions="";
eval(javascript);//执行从服务端返回的javascript代码
for(vari=0;i<options.length;i++)//从options数组中取数据
{
vars="";
if(isIE())
{
select.options[select.options.length]=newOption(options[i],options[i]);
}
else
{
myOptions+="<optionvalue='"+options[i]+"'>";
myOptions+=options[i];
myOptions+="</option>"
}
}
}
varid=select.id;
if(!isIE())
select.innerHTML=myOptions;
}
在上面的addOptions方法中还有一个不同是在IE中使用了<select>对象的options数组来添加选择项,而不是使用outerHTML。这么做的好处是可以在onLoad方法中就获得<select>的选项值。而如果使用outerHTML在html未装载完时,<select>标签中选择项仍然为0。这样在onLoad方法中就无法访问<select>中的被加入项了,当然,在onchange事件中可以。
在firefox中使用innerHTML时,在html未装载完时,只要<select>标签被装载完(也就是调用了addOptions方法后),就可以访问<select>标签中的<option>了。个人感觉这一点要从IE做得好。顺便说一句,笔者使用的是IE6,不知道ie7会是什么效果。如果哪位试过,可以跟贴。图1是本例的效果图。

分享到:
相关推荐
例如,我们创建一个函数fetchData(),该函数使用Ajax从后台获取数据,然后用setInterval()定时调用这个函数。 ```javascript function fetchData() { var xhr = new XMLHttpRequest(); xhr.onreadystatechange = ...
本文将深入探讨如何使用Ajax向PHP服务端发送请求,并接收JSON格式的数据。 Ajax的核心是JavaScript的XMLHttpRequest对象,它允许我们在不刷新整个页面的情况下与服务器进行通信。以下是一个基本的Ajax请求示例: `...
AJAX (Asynchronous JavaScript and XML) 是一种创建动态网页的技术,允许在不刷新整个页面的情况下从服务器获取数据并更新部分网页内容。这个示例包含客户端和服务器端的源码,旨在展示如何使用jQuery实现AJAX功能...
这个演示网站的业务原型来自于Northwind,但所有的表都是我重新根据示例需要而重新定义的, 数据来源于以前从网页上获取的数据,虽然不真实,但更适合于演示。于Northwind不同的是,为了示例, 所有的数据库操作全...
首先,`AutoQueryTextBox.aspx`是一个ASP.NET页面,它包含了一个TextBox控件,用户在此输入时,将触发Ajax请求以获取与输入匹配的服务端数据。页面可能还包含其他元素,如一个隐藏的UpdatePanel或一个用于显示结果的...
在 Ajax 中,GET 请求通常用于从服务器获取数据,如查询信息。 2. **POST**:POST 方法用于向服务器发送数据,比如用户填写表单后提交数据。在 Ajax 中,POST 请求常用于更新或创建新资源。 3. **JSONP**:JSON ...
本实例主要探讨的是如何通过"grid"这种数据展示组件从服务端获取数据,并利用特定的事件触发方法来实现这一过程。"grid"通常指的是表格或者网格布局,常用于展示结构化数据。在这个例子中,我们将关注JavaScript的...
3. **Ajax请求**:使用XMLHttpRequest对象或jQuery的`$.ajax()`方法发送异步请求到服务器,请求的数据通常包含用户当前选中的级别和值。 4. **服务器端处理**:服务器接收到请求后,根据传入的参数查询数据库,获取...
使用fetch时,可以使用`response.text()`方法获取数据,然后手动转换为JSON,这样可以更容易地处理包含非标准格式的数据。 总之,处理Ajax返回带有换行的JSON数据的关键在于确保数据符合JSON规范,无论是服务端处理...
客户端通常是指Web应用的前端部分,可以使用JavaScript(配合AJAX)或者现代的前端框架如React、Vue.js来获取服务端的JSON数据。以JavaScript的fetch API为例,展示如何获取JSON: ```html <!DOCTYPE html> , ...
总的来说,通过Ajax获取服务器端的JSON数据是Web开发中的常见操作,掌握这一技能对于进行动态交互的Web应用开发至关重要。了解并熟练使用Ajax和JSON,能够帮助开发者更高效地构建前后端通信,提供流畅的用户体验。
使用`XMLHttpRequest`或更现代的`fetch API`发送Ajax请求获取数据。这里以`fetch API`为例: ```javascript fetch('api-url?provinceId=' + selectedProvinceId) .then(response => response.json()) .then(data ...
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,由于其与JavaScript语法的紧密关联,成为AJAX传输数据的首选格式。在"ajax操作json数据"这个主题中,我们将深入探讨如何使用AJAX来处理和解析JSON...
在IT行业中,服务端模拟AJAX请求是一种常见的测试和开发技术。这主要涉及到Web应用程序的交互,特别是客户端(浏览器)与服务器之间的异步数据通信。本文将深入探讨如何使用JavaScript来模拟GET、POST、PUT和DELETE...
在实现Ajax功能时,开发者可能需要在SqlYog中编写SQL语句来处理数据的增删改查,然后在SSM项目中配置MyBatis的Mapper文件,将SQL语句映射到Java方法上,以便在服务端处理Ajax请求。 具体到文件名"exam_4",这可能是...
**AJAX页面无刷新实现数据更新** 在网页开发中,用户界面的实时性和交互性是提升用户体验的关键因素。AJAX(Asynchronous JavaScript and XML)技术就是为了解决这个问题而诞生的,它允许网页在不重新加载整个页面...
首先,让我们理解标题中的关键词:“Ajax”是一种在不刷新整个页面的情况下与服务器进行异步通信的技术,它由四个主要部分组成:发送请求、接收响应、处理数据以及更新页面。而“PHP”是一种服务端脚本语言,常用于...
在微信小程序中,实现从服务器获取数据并进行模板遍历显示是常见的功能需求。本示例将详细讲解如何使用微信小程序的内置API `wx.request` 来实现Ajax请求,并利用模板`wx:for`进行数据循环渲染。 1. **wx.request**...
本案例将探讨这两种接口从服务端(服务器)到客户端(浏览器)的实现,主要涉及MVC(Model-View-Controller)框架和WebApi技术。 1. **HTTP方法:GET与POST** - GET:主要用于获取资源,它将请求参数附加到URL上,...