用Ajax实现的联动列表

     由于昨天把博客装饰好了,今天就来分享一下我以前做过的一个用Ajax实现的联动列表。

    平常我们用服务器控件实现的多列表联动,在每次选择一项的时候都会刷新页面,如果页面元素过多,这样会使用户体验十分差。而我们用Html写死的联动列表会使一次的传输量比较大,而且可能会使一些被更新的内容不能及时展示给用户。所以才需要用Ajax来实现,Ajax可以应用在很多方面,但是不能被滥用。

    前阵子有空的时候,做了一个Ajax的联动列表和Ajax的TreeView,不过后来项目任务比较多,就没有完成它们了,这个顶多是个半成品。

    做这个的时候,当时的思想是不仅做好前端与后台的互动,而且要做好后台的API,让不懂前端的后台们能够轻易用上这两个东西,现在做好的仅仅是前端部分。

      下面注释写得算是详细吧,有不懂的或者改进意见的可以随便说出来哦~

Ajax.js(用来和服务器交互)

 

代码
 
   


var net = new Object();
net.ContentLoader
= function (url, onload, onerror) {
this .url = url;
this .onload = onload; // 请求完之后发生的事件
this .req = null ; // XHR实例,现在初始化为空
this .onerror = (onerror) ? onerror : this .defaultError; // 如果onerror存在,那么在发生错误时执行onerror,否则执行默认错误处理
this .loadXMLDoc();
}

net.ContentLoader.prototype
= {
loadXMLDoc:
function (url) {
if (window.XMLHttpRequest) { this .req = new XMLHttpRequest(); } // 获取XHR对象
else {
try { if (window.ActiveXObject) { this .req = new ActiveXObject( " Msxml2.XMLHTTP " ); } }
catch (a) { this .req = new ActiveXObject( " Microsoft.XMLHTTP " ); }
}


},
onReadyState:
function () {
var req = this .req;
var ready = req.readyState;
if (ready == 4 ) { // 当readyState为4的时候,证明请求已经完成
var httpstatus = req.status;
if (httpstatus == 200 || httpstatus == 0 ) // 当Status为200的时候请求正常,但是有时会出现为0的状况,没搞清楚
{ this .onload.call( this ); }
else { this .onerror.call( this ); }
}


},
sendAjax:
function (querySting) {
// 把查询字符串从URL传入
if ( this .req) {
try {
// 这里利用了闭包,因为onReadyState触发的时候,this总是指向Window对象,而不是我们期待的ContentLoader对象本身,
// 所以用call方法和闭包,使onReadyState的上下文对象改变为ContentLoader对象本身
var loader = this ;
this .req.onreadystatechange = function ()
{ loader.onReadyState.call(loader); }
// 运用时间戳,因为有些浏览器会缓存页面,如果请求URL相同的话,有可能会请求不到实时数据,加了时间戳可以避免这些状况
var data = new Date();
var Time = data.getTime();
this .req.open( " GET " , this .url + querySting + " &time= " + Time, true );
this .req.send( null );
}
catch (error) {
this .onerror.call( this ); // onerror方法的上下文也要是这个ContentLoader对象
}

}


},
defaultError:
function () {
alert(
" error! " + " \n\nreadyState: "
+ this .req.readyState
+ " \nstatus: "
+ this .req.status
+ " \nherders: "
+ this .req.getAllResponseHeaders());

}

}

 

ListSample.js(这个的作用相当于MVC里面的Control,也是基于组件化思想开发的,前台页面使用这个联动List的时候,只要几行代码就行了)

 

 

代码
 
   

function ListCon(masterId, slaveId,url,paramOption) {

this .slaveId = document.getElementById(slaveId); // 根据从方ID,获取从方Dom对象
this .paramOption = paramOption; // 保存参数对象
this .req = new net.ContentLoader(url, this .buildList); // 建立ContentLoader对象,并指定回调方法为this.buildList
this .req.LC = this ; // 保存自己的方向连接到ContentLoader对象

if (masterId != null ) {
// 如果有主方ID,那么证明不是第一个List,则获取主方对象
this .masterId = document.getElementById(masterId);
this .masterId.next = this .slaveId; // 主方对象保存从方对象的引用
// 以下方法是用来当前面的List发生变动时来清空其后面所有后面的List
this .masterId.clearBehind = function () {
var slave = this .next; // next即为下一个的意思
slave.options.length = 0 ; // 清空
var option = document.createElement( ' option ' ); // 一项都没很难看,加上默认项
option.value = 0 ;
option.text
= " ---- " ;
slave.options.add(option);

if (slave.clearBehind) { slave.clearBehind(); } // 如果slave不是最后一个,那么就会有clearBehind方法,那么就递归清空后面的
}


this .Init(); // 初始化
}

else {
this .masterId = new Object(); // 为了兼容有masterId的ListCon对象,这里要构造出一个Object来顶替
this .masterId.next = this .slaveId;
this .masterId.clearBehind = function () { }
this .masterChange(); // 自动载入第一个List的数据,这也是联动的第一个List



}
}

// 构造ListCon.prototype
ListCon.prototype = {
Init:
function () {
var othis = this ; // 这里也用到了闭包,同理是因为onchange里面的上下文this不是指向ListCon对象,所以要用这种方法来调用masterChange();
this .masterId.onchange = function () { othis.masterChange(); }
},
masterChange:
function () {
var params = this .paramOption;
var sendString = " ? " ;
if (params.type != " noparams " ) // 如果没有参数,那么就是第一个List
{
sendString
= sendString + " q= " + this .masterId.options[ this .masterId.selectedIndex].value;
sendString
= sendString + " &slavetable= " + this .masterId.id;
}
sendString
= sendString + " &type= " + params.type;
sendString
= sendString + " &table= " + params.table;

this .req.sendAjax(sendString)
},
buildList:
function () {
var options = eval( ' ( ' + this .req.responseText + ' ) ' ); // 传回的数据是json

var optionslength = options.length;
this .LC.masterId.clearBehind();
this .LC.slaveId.options.length = 0 ;

if (optionslength != 0 ) {


var option = document.createElement( ' option ' ); // 创建默认项,“请选择”
option.value = 0 ;
option.text
= " 请选择 " ;
this .LC.slaveId.options.add(option);


for ( var i = 0 ; i < optionslength; i ++ ) // 这里由数据模型options创建视图
{
var option = document.createElement( ' option ' );
option.value
= options[i].Value;
option.text
= options[i].Text;
this .LC.slaveId.options.add(option);

}
}
else {
// 如果返回的数据模型是空的,那么做以下处理
var option = document.createElement( ' option ' );
option.value
= 0 ;
option.text
= " ---- " ;
this .LC.slaveId.options.add(option);

}
// if (this.LC.slaveId.onchange)
// { this.LC.slaveId.onchange(); }
}
}
function creatParamsOption(table,type)
{
this .table = table;
this .type = type;
}

 

List.htm(前台页面)

 

 

代码
 
   
<! DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" >

< html xmlns ="http://www.w3.org/1999/xhtml" >
< head >
< title ></ title >
< script type ="text/javascript" src ="AjaxHelp.js" ></ script >
< script type ="text/javascript" src ="ListSample.js" ></ script >
< script >
window.onload
= function () {

new ListCon( null , " Country " , " SendlistHandler.ashx " , new creatParamsOption( " Country " , " noparams " )); // 因为这个是第一个list所以没有主List
new ListCon( " Country " , " City " , " SendlistHandler.ashx " , new creatParamsOption( " City " , " params " ));
new ListCon( " City " , " School " , " SendlistHandler.ashx " , new creatParamsOption( " School " , " params " ));

}
</ script >
</ head >
< body >

< select id ="Country" name ="D1" >
< option value =0 selected ="selected" > 请选择 </ option >
</ select >< select id ="City" name ="D2" >
< option value =0 selected ="selected" > ---- </ option >
</ select >< select id ="School" name ="D3" >
< option value =0 selected ="selected" > ---- </ option >
</ select >

</ body >
</ html >

 

我们可以清楚的看到,组件式开发Ajax功能组件的时候,有复用性好,使用简单等特点。

 

 

这个组件仅仅据有联动功能,其实还有很多特性可以加上去,比如像前面说的,可以在后台写个配合这个的类,提供API给其他人用,以后有空再做吧~

转载于:https://www.cnblogs.com/Pola/archive/2010/09/21/1832480.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值