写一个ajax程序就是如此简单

 479  2009/02/19 16:41:00


      ajax介绍:

          1:AJAX全称为Asynchronous JavaScript and XML(异步JavaScript和XML),指一种创建交互式网页应用的网页开发技术。

      2:基于web标准XHTML+CSS的表示;

      3:使用 DOM进行动态显示及交互;

      4:使用 XML 和 XSLT 进行数据交换及相关操作;

      5:使用 XMLHttpRequest 进行异步数据查询、检索;

     程序员应用ajax的途经:

          1:.Net下的AjaxPro,引入AjaxPro.2.dll,在前台页面JS调用后台页面的方法;

          2:微软的AJAX组件,添加AjaxControlToolkit.dll,或者是ASP.NET AJAX;

          3:开源的ajax框架。

          4:自己写ajax脚本。

     不过觉的前三种无论是哪一种,都觉的有点复杂,虽然它们如此强大,能做出很多特别优秀的无刷新效果,但开发人员都必须依赖它,开必人员只要学习怎么调用它就行,至于其中的原理大可忽略,即使你想学习它的原理,没有相当的js水平,怕是徒劳无功。如果需求并没有这么高,只是简单的通过无刷新实现访问后台代码然后操作DOM对象呢,还有必要引入这种大家伙吗?个人认识没有必要,理由如下:

          1:有种杀鸡用牛刀的感觉;

          2:引入第三方框架会使已有应用程序更加复杂;

          3:js框架都不小,在每个网页中引入这些js文件对网络传输肯定会有部分影响。

          4:如果框架中没有提供你要的功能,那又如何? 如何实现个性化定制?

      ajax虽然流行了好几年了,但本人07年初才用上,当时公司同事有用ajaxPro的,但用过了实在了感觉不好用,有时往往会出现些莫名其妙的问题。后来在书店发现在《征服ajax系列》,才发现实现简单的ajax程序其实并不难,一个ajax程序处理过程如下:

      第一:创建XMLHttpRequest,不同的浏览器创建的方式不同;

      第二:发送请求。调用XMLHttpRequest的open()和send()方法:

          1:xmlhttp_request.open('GET', URL, true);

                  第一个参数:HTTP请求方式—GET,POST;

              第二个参数:请求页面的URL;

              第三个参数:请求是否为异步模式。如果是TRUE,JavaScript函数将继续执行,而不等待服务器响应。

          2:xmlhttp_request.send(null);


       第三:服务器的响应。

                1:告诉HTTP请求对象用哪一个函数处理这个响应。对象的onreadystatechange属性设置为要使用的JavaScript的函数名:xmlhttp_request.onreadystatechange =FunctionName;FunctionName是用JS创建的函数名,也可直接将JS代码创建在onreadystatechange之后,例如:


xmlhttp_request.onreadystatechange = function()
{
// JavaScript代码段
};

  

               2:检查请求的状态。XMLHttpRequest 提供了readyState属性来对服务器响应进行判断。readyState的取值如下:0 (未初始化);1 (正在装载);2 (装载完毕);3 (交互中);4 (完成)。所以只有当readyState=4时,函数才可以处理该响应。具体代码如下:接着,函数会检查HTTP服务器响应的状态值。当HTTP服务器响应的值为200时,表示状态正常。 

if (http_request.readyState == 4
// 收到完整的服务器响应 }
else { // 没有收到完整的服务器响应 }

      第四:处理从服务器得到的数据。有两种方式可以得到这些数据:

         1: 以文本字符串的方式返回服务器的响应;

            2: 以XMLDocument对象方式返回响应

      具体案例:我们有一批礼品想要送给用户,一般都会以文字列表的形式列出来,礼品名称上给个链接,当用户点击链接时弹出一个窗口显示这个礼品的详细描述信息,当用户选中下拉框按钮时判断这个礼品在送给用户前需要不需要用户填写地址,如果要则动态在页面加载相应的输入框。下面是两张效果图,一张时无需用户录入联系地址的,一张需要。



      第一:引用封装好的XmlHttp.js,这个包含了创建XMLHttpRequest对象,以及发送请求与加载回调方法的函数,前端开发人员只需要传递简单的几个参数就可以实现异步调用,代码如下:

//------------------------------------------------------------------------------------------

//封装XMLHTTP的Request类的代码
var Request = new Object();
//定义一个XMLHTTP的数组

Request.reqList 
= [];
//创建一个XMLHTTP对象,兼容不同的浏览器

function getAjax()
{
    var ajax
=false;
    
try
    {
     ajax 
= new ActiveXObject("Msxml2.XMLHTTP");
    }
    
catch (e)
     {
      
try
      {
      ajax 
= new ActiveXObject("Microsoft.XMLHTTP");
      }
     
catch (E)
      {
      ajax 
= false;
      }
    }
    
if (!ajax && typeof XMLHttpRequest!='undefined')
    {
     ajax 
= new XMLHttpRequest();
    }
    
return ajax;
}
//封装XMLHTTP向服务器发送请求的操作
//url:向服务器请求的路径;method:请求的方法,即是GET还是POST;callback:当服务器成功返回结果时,调用的函数
//data:向服务器请求时附带的数据;urlencoded:url是否编码;callback2;当服务器返回错误时调用的函数
Request.send = function(url, method, callback, data, urlencoded, callback2)
 {
    var req
=getAjax();  //得到一个XMLHTTP的实例

    
//当XMLHTTP的请求状态发生改变时调用
    req.onreadystatechange = function()
    {
    
// 当请求已经加载

    
if (req.readyState == 4)
    {
            
// 当请求返回成功

            
if (req.status < 400)
            {
            
// 当定义了成功回调函数时,执行成功回调函数
            if(callback)
                callback(req,data);
            }
            
// 当请求返回错误

            
else
            {
                
                
//当定义了失败回调函数时,执行失败回调函数
                if (callback2)
                callback2(req,data);
            }
            
            
//删除XMLHTTP,释放资源

            
try {
                delete req;
                req 
= null;
            } 
catch (e) {}
        }
    }
    
//如果以POST方式回发服务器

    
if (method=="POST")
     {
        req.open(
"POST", url, true);
        
//请求需要编码

        
if (urlencoded)
            req.setRequestHeader(
'Content-Type''application/x-www-form-urlencoded');        
        req.send(data);
        Request.reqList.push(req);
    }
    
//以GET方式请求
     else
    {
        req.open(
"GET", url, true);
        req.send(
null);
        Request.reqList.push(req);
    }
    
    
return req;
}
//全部清除XMLHTTP数组元素,释放资源

Request.clearReqList 
= function()
{
    var ln 
= Request.reqList.length;
    
for (var i=0; i<ln; i++) {
        var req 
= Request.reqList[i];
        
if (req)
        {
        
try
        {
            delete req;
        } 
catch(e) {}
        }
    }
    Request.reqList 
= [];
}
//进一步封装XMLHTTP以POST方式发送请求时的代码

//clear:是否清除XMLHTTP数组的所有元素;其他参数的意义参见Request.send
Request.sendPOST = function(url, data, callback, clear, callback2)
{
    
if (clear)
        Request.clearReqList();
    Request.send(url, 
"POST", callback, data, true, callback2);
}
//进一步封装XMLHTTP以GET方式发送请求时的代码

Request.sendGET 
= function(url,args, callback,clear, callback2)
{
    
if (clear)
        Request.clearReqList();
    
return Request.send(url, "GET", callback, args, false, callback2);
}

      第二:引用一个工具js:CommJM.js,一般是为了代码共享而引入的。

var controleID="";
var innerHtml
="";
//给控件赋值
function $$(controleID ,innerHtml )
{
  var _controleID
=$(controleID );
  _controleID .innerHTML
=innerHtml ;

}
//隐藏控件
function hideObject(controleID)
{
  var _controleID
=$(controleID );
  _controleID.style.display 
= "none";
 
}
//显示控件
function showObject(controleID)
{
  var _controleID
=$(controleID );
  _controleID.style.display 
= "block";
}
var controlsID
="";
    
//by minjiang 07-11-02
    function $(controlsID)
    {
      
return document .getElementById (controlsID );     
    }

      第三:创建ajax请求页面:ajax_promotion.aspx,把这个页面的HTML代码除了<%@ Page Language="C#"这行之外,全部删除。

      第四:在ajax_promotion.aspx页面的后台代码中写相关业务操作。

//取得奖品ID
        string giftID = "";
        
//当前促销活动方案ID
        string currentTarget = "";
        xmlProvider _xmlProvider 
= null;
        
protected void Page_Load(object sender, EventArgs e)
        {
            
            
this.action();         
        }
        
private void action()
        {
            
//业务处理类型
            string sAction = "";
            
if (Request.QueryString["action"!= null && Request.QueryString["action"!= "")
            {
                sAction 
= Request.QueryString["action"].Trim();
            
            }
            
switch (sAction)
            {
                
case "getInput":
                    
//判断用户选择的礼品是否需要录入联系方式
                    this.getInput();
                    
break;
                
case "getDescription":
                    
this.getDescription();
                   
break;          
            }       
        }
        
/// <summary>
        
/// 判断是否需要录入联系方式
        
/// </summary>
        private void getInput()
        {
                   
        }
        
/// <summary>
        
/// 取某一奖品的详细说明信息
        
/// </summary>
        private void getDescription()
        {
                 
        }

       第四:在前端页面中实现异步调用。

               第一:页面头部代码。

//引入相关js文件
<script language ="javascript" type ="text/javascript" src ="XmlHttp.js"></script>
<script language ="javascript" type ="text/javascript" src ="CommJM.js" ></script>
<script language ="javascript" >
//奖品ID
var giftID=1;
//根据奖品ID读取奖品的描述信息
function getDescription(giftID)
{
    var sUrl
="ajax_promotion.aspx?id="+giftID+"&i="+Math.random()+"&action=getDescription";
   Request.sendGET(sUrl,
null,getCallBack,true,null);
}
//根据奖品ID读取奖品的描述信息的回调方法
  function getCallBack(req,data)
  {
        
//alert("进入回调方法");
         var strResult=req.responseText;
         
//alert(strResult);
        if(strResult!="")
        {
           $$(
"jl01_layer",strResult);
    
        }      
  }
  
//根据奖品ID取得这奖品是否需要录入用户的联系方式
  function getInput(giftID)
  {
       var sUrl
="ajax_promotion.aspx?id="+giftID+"&i="+Math.random()+"&action=getInput";
       
//alert(sUrl);
       Request.sendGET(sUrl,null,getInputCallBack,true,null);
  }
  
//getInput回调方法
  function getInputCallBack(req,data)
  {
        
//alert("进入回调方法");
         var strResult=req.responseText;
         
//alert(strResult);
        if(strResult=="true")
        {
           showObject(
"<%= this .BlkBlackTabcontent_11 .ClientID %>");
    
        }
        
else
        {
            hideObject(
"<%= this .BlkBlackTabcontent_11 .ClientID %>")
        }
  }
</script>

 

               第二:页面代码:

<input id="ctl08_rbl_Gift_0" type="radio" name="ctl08$rbl_Gift" value="1" onclick="getInput('1');" />
<label for="ctl08_rbl_Gift_0">
<a href="#" onclick="cc(this,'jl01_layer','1')">
 礼品名称
</a>
</label>

 

      总结:从整个过程来看,对于开发员来说代码量并不大,如果有了上面两个封装好的js文件,以后的开必就轻松多了,只关心复杂业务逻辑的处理以及页面效果,页面效果倒是需要额外的工作,最好具备一定的js能力。我们可以从其它js框架了抽取自己需要的部分放入自己的公用类库中,这样就形式了一套适合自己的js框架,方便又实用。

      补充:这篇文章并不在于技术有多深,而在于一种工作模式,做适合自己项目的框架,远比用些看起来功能特别强大的框架来的方便。据园友的问题我想说明几点:

              1:从性能上来讲,有的框架十来个js文件,而且还是压缩的,在网络传输时会有一定影响;

              2:具体项目能调用的功能占整个框架功能的百分比。如果只是整个框架功能的10%,或者更少,引入框架值得吗?

              3:自己开发脚本库时间长了,不也成了一个框架了吗?和其它的框架有什么区别呢?

                   第一:当然会成为一个框架;

                   第二:自己写的框架怎么会和别人写的框架一样呢?

                            <1>:自己的框架是自己根据具体项目具体需求来写的,很多框架中不实用的功能并不会引进来;

                            <2>:在调试上,自己的框架当然占优势,自己写的东西肯定能第一时间知道问题的出处。

             4:自己开发框架,时间长了不也锻炼了自己的js能力吗?

             5:本文并不是排斥框架,也不是说在项目中不能用框架,而是希望从实际项目考虑,全面比较框架在项目中优劣性。

             6:不要过分依赖框架,试想下在没有框架前,你的工作怎么办?用框架永远在别人之后。

             7:ajax框架支持很多特别复杂的动画效果,这是手工完成难度特别大的地方,而且框架对程序员要求相对要抵,而且容易形成统一的代码风格,理性分析利弊再决定是否用框架。

             8:自己写脚本,并不代表每个项目或者是每个页面都需要自己把所有方法都重写一次,当然会考虑到代码复用了,谁会在每个页面中都写 documemt.getelememtById啊,你不觉得烦,别人看起来也烦,如果封闭一个$()方法,不更好?而且这种方式都是从框架中学来的,要消化成自己的。

             9:自己写脚本的目的:吸取多个框架的特点,取长补短,做适合自己的,如果你的项目中对动画什么的没有要求,那么就不会引入这些额外的没用的js,无论怎么写,肯定不能都自己写,需要借助已有成熟的产品,但不能拿来主义。

 

注:

   本文引用:http://baike.baidu.com/view/1641.htm

本文转自:http://www.cnblogs.com/ASPNET2008/archive/2009/02/19/1394044.html