<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆 - 312, 文章 - 14, 評論 - 1393, 引用 - 0
    數據加載中……

    AJAX從服務端獲取數據的三種方法

    本文為原創,如需轉載,請注明作者和出處,謝謝!

        在本文中將給出一個例子來介紹使用AJAX技術從服務端獲得數據的三種方法。這個例子很簡單,就是兩個選擇框(html中的<select>標簽),通過選中第一個select的某一項后,會從服務端得到一些數據,并加載到第2select中。

    方法一、從服務端獲得XML格式的數據

    從服務端獲得數據的最容易想到的方法就是在服務端反加一定格式的數據,一般是XML格式,然后在服務端使用XMLDocument或其他技術來讀取這些數據,并生成<select>標簽中選項的格式文本(<option>標簽)。下面的addOptions函數是這個例子的核心函數,它負責根據從服務端獲得的數據生成<select>標簽中的<option>標簽。在這里所使用的方法是利用了<select>標簽的innerHTML屬性(僅限于firefox),如果是IE,要使用outerHTML屬性(IE<select>標簽的innerHTML屬性有一些小bug,讀者可以試著在IE中使用innerHTML屬性,看看會發生什么情況)。addOptions方法的實現代碼如下:

    // select表示<select>對象,xml表示XMLDocument對象
    function addOptions(select, xml)
    {    
        
    if(select)
        {
            
    var options = "";
            
    for(var i = 0; i < xml.childNodes[0].childNodes.length ; i++)
            {  
                
    if(xml.childNodes[0].childNodes[i].nodeName == "list")
                {
                    
    var s = "";
                    
    if(isIE())               
                        s 
    = xml.childNodes[0].childNodes[i].text;         
                    
    else
                        s 
    = xml.childNodes[0].childNodes[i].textContent
                    options 
    += "<option value='" + s + "'>" ;
                    options 
    += s;
                    options 
    += "</option>"
                }
            }
                
            
    var id = select.id;
            
    if(isIE())
                select.outerHTML 
    = "<SELECT id='" + id + "' onchange='onChange(this)'>" + options + "</SELECT>";
            
    else
                select.innerHTML 
    = options;                
            
        }
    }

        onReadState函數將在XMLHttpRequest對象的異步訪問服務端時調用。當readyState4時表示成功從服務端返回XML數據。這個函數的實現代碼如下:


    // myRequest表示XMLHttpRequest對象,selectId表示<select>標簽的id屬性值
    function onReadyState(myRequest, selectId) 

        
    if(myRequest.readyState == 4)   // 4表示成功獲得相應信息
        {              
            
    try
            {
                
    var xml = myRequest.responseXML;   // 獲得XMLDocument對象      
                var kind = document.getElementById(selectId); // 獲得<select>對象
                addOptions(kind, xml);  // 向<select>標簽中加入<option>標簽
            }
            
    catch(e)
            {
                alert(
    "onReadyState:" + e);
            }
        }
    }

        getData函數負責向服務端發送請求,并設置異步事件。實現代碼如下:

    function getData(url, selectId)
    {
        
    var myRequest = 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代碼。

    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html>
        
    <head>
            
    <title></title>
            
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
            
    <script type="text/javascript" src="myscript.js">
            
    </script>
        
    </head>
        
    <body>
            
    <select id="bigKind" onchange="onChange(this)" >
                 
            
    </select>
            
    <select id="smallKind" >
               
            
    </select>
        
    </body>
    </html>

     
        從上面代碼可以看出,這兩個<select>標簽分別是bigKindsmallKind,里面并沒有<option>標簽,這是因為<option>標簽要在javascript里動態加載。下面我們先來加載bigKind中的數據。

    window.onload = onLoad
    function onLoad()
    {                         

        
    try
        {
            getData(
    "../GetXML""bigKind");
                   
        }
        
    catch(e)
        {
            alert(
    "onLoad:" + e);
        }
    }


         其中GetXML是一個Servlet程序(讀者可以將其換成其他的服務端程序,如asp.netphp的)。下面是這個GetXML程序的實現代碼:

    package servlet;

    import java.io.*;
    import javax.servlet.*;
    import javax.servlet.http.*;
    import database.MyData;

    public class GetXML extends HttpServlet
    {

        
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
                
    throws ServletException, IOException
        {
            response.setContentType(
    "application/xml;charset=UTF-8");

            PrintWriter out 
    = response.getWriter();

            
    try
            {
                String s 
    = request.getParameter("kind");

                out.println(
    "<data>");
                
    if (s == null)
                {
                    
    for (String key : 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 (String kind : smallKind)
                        {

                            out.println(
    "<list>" + kind + "</list>");
                        }
                    }
                }
                out.println(
    "</data>");

            } 
    finally
            {
                out.close();
            }
        }

        
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
                
    throws ServletException, IOException
        {
            processRequest(request, response);
        }

        
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
                
    throws ServletException, IOException
        {
            processRequest(request, response);
        }

        
    public String getServletInfo()
        {
            
    return "Short description";
        }
    }

     

       不管讀者會不會javaservlet,從這個程序中的processRequest方法中都可以看出,首先會獲得請求參數kind,如果這個參數不存在,則返回bigKind所需要的數據,以xml格式返回,類似于如下的格式:

    <data>
      
    <list>data1</list>
      
    <list>data2</list>
    </data>


        如果kind參數存在,則在MyData.data中查詢第2<select>標簽(smallKind)所需要的數據。data是一個Map類型。為了方便起見,本例子并未使用數據庫,而是在MyData類中定義了一個靜態的Map類型變量。MyData的實現代碼如下:

    package database;

    import java.util.*;

    public class MyData {

        
    public static Map<String, List<String>> data;    

        
    static {
            
            data 
    = new HashMap<String, List<String>>();
            
            List
    <String> eProducts = new LinkedList<String>();
            eProducts.add(
    "手機");
            eProducts.add(
    "數碼/IT");
            eProducts.add(
    "家電");
            eProducts.add(
    "電腦");
                    
            data.put(
    "消費電子", eProducts);
            
            List
    <String> goods = new LinkedList<String>();
            
            goods.add(
    "化妝");
            goods.add(
    "健康");
            goods.add(
    "玩具");
            goods.add(
    "辦公/文體 ");
            goods.add(
    "童裝童鞋");
            goods.add(
    "其他");
            
            data.put(
    "日用百貨", goods);
            
            List
    <String> books = new LinkedList<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事件函數的代碼如下:

    function onChange(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方法中可以找到如下的一條語句:

    = java.net.URLDecoder.decode(s, "UTF-8");


        就是進行解碼操作。

        注:如果在IE中,客戶端可以不使用encodeURI對帶中文的URL進行編碼,服務端也不用解碼。在服務端仍然可以正常顯示中文。但在firefox中就必須要進行編碼和解碼。因此,要想跨瀏覽器,就需要使用本文所述的方法。

    方法二、直接獲得<option>...</option>內容的字符串

        上面的獲得數據的方法是從服務端獲得了一個XML文檔,并轉換成XMLDocument對象,然后解析。這種方法雖然很好,但是操作XMLDocument對象還是有些麻煩,因此,我們可以在服務端直接反回<select>標簽所需要的<option>標簽字符串,然后將這些字符串傳給<select>對象的innerHTMLouterHTML就可以了。服務端的代碼和上面的實現代碼類似,只需要將<data>去掉,然后將<list>改為<option>后,并使用如下的語句來設置ContentType

    response.setContentType("text/html;charset=UTF-8");

    客戶端可通過XMLHttpRequest對象的responseText屬性獲得這些含有<option>的文本,并將其賦給innerHTMLouterHTML屬性。這種方法雖然很方便,但并不靈活。如果客戶端不使用<select>標簽,而是使用<table>或其他的標簽顯示數據,那么返回的這些數據就沒什么用處了。而即方便,又靈活的應該是下面要介紹的方法。

    方法三、從服務端返回javascript代碼,在客戶端使用eval函數執行

        我們可以在服務端返回類似于如下的字符串:

        var options = new Array();

        options.push(‘data1’);

        options.push(‘data2’);

        然后使用eval函數執行上面的字符串,這樣我們在javascript中就可以使用options數組了。我個人認為,使用數組要比使用XMLDocument更容易,代碼量也更少。如果要返回更為復雜的數據,也可以使用javascript中的類或其他數據結構。根據上面的思想,新的processRequest方法的代碼如下:

        protected void processRequest(HttpServletRequest request, HttpServletResponse response)
                
    throws ServletException, IOException
        {
            response.setContentType(
    "text/html;charset=UTF-8");

            PrintWriter out 
    = response.getWriter();
            out.println(
    "var options = new Array();");
            
    try 
            {
                String s 
    = request.getParameter("kind");


                
    if (s == null)
                {                
                    
    for (String key : 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 (String kind : smallKind)
                        {
                            out.println(
    "options.push('" + kind + "');");
                        }
                    }
                }

            } 
    finally
            {
                out.close();
            }
        }

        客戶端經過改進的addOptions函數如下:

    // javascript表示從服務端返回的javascript代碼字符串
    function addOptions(select, javascript)
    {    
        
    if(select)
        {   
            
    if(select.id == "smallKind")
            {
                
    if(isIE())
                    select.options.length 
    = 0
            }
            
    var myOptions = "";
            eval(javascript);  
    //執行從服務端返回的javascript代碼
            for(var i = 0; i < options.length ; i++)  // 從options數組中取數據
            {             
                
    var s = "";
                
    if(isIE()) 
                {
                    
                    select.options[select.options.length] 
    = new Option(options[i], options[i]);
                }
                
    else
                {
               
                    myOptions 
    += "<option value='" + options[i] + "'>" ;
                    myOptions 
    += options[i];
                    myOptions 
    += "</option>"
                }
            }
        }
           
        
    var id = select.id;
        
    if(!isIE())    
            select.innerHTML 
    =  myOptions;           
    }


        在上面的addOptions方法中還有一個不同是在IE中使用了<select>對象的options數組來添加選擇項,而不是使用outerHTML。這么做的好處是可以在onLoad方法中就獲得<select>的選項值。而如果使用outerHTMLhtml未裝載完時,<select>標簽中選擇項仍然為0。這樣在onLoad方法中就無法訪問<select>中的被加入項了,當然,在onchange事件中可以。 

        firefox中使用innerHTML時,在html未裝載完時,只要<select>標簽被裝載完(也就是調用了addOptions方法后),就可以訪問<select>標簽中的<option>了。個人感覺這一點要從IE做得好。順便說一句,筆者使用的是IE6,不知道ie7會是什么效果。如果哪位試過,可以跟貼。圖1是本例的效果圖。



                                   圖1

        本來想提供asp.net的例子來著,結果不知怎么著,vs2008asp.net設計視圖突然不響應了,誰知道是怎么回事啊??





    Android開發完全講義(第2版)(本書版權已輸出到臺灣)

    http://product.dangdang.com/product.aspx?product_id=22741502



    Android高薪之路:Android程序員面試寶典 http://book.360buy.com/10970314.html


    新浪微博:http://t.sina.com.cn/androidguy   昵稱:李寧_Lining

    posted on 2008-05-25 23:16 銀河使者 閱讀(7795) 評論(18)  編輯  收藏 所屬分類: javaajaxjavascript 原創

    評論

    # re: AJAX從服務端獲取數據的三種方法  回復  更多評論   

    第一種方法通用性比較好,但比較復雜。
    第二種方法比較直接簡單。
    第三種方法比較垃圾。
    2008-05-26 10:28 | javajava

    # re: AJAX從服務端獲取數據的三種方法  回復  更多評論   

    不過我認為第3種方法比較好,可以使客戶端編程更容易,也更直觀。如果返回的xml比較復雜,使用第一種方法,javascript代碼會很多。

    但在實現項目中,這三種方法可以混合使用。
    2008-05-26 10:39 | 銀河使者

    # re: AJAX從服務端獲取數據的三種方法  回復  更多評論   

    innerHTML屬性在IE里有一點bug,我好像還沒碰到過。我用的是IE6.0
    2008-05-27 01:30 | 無花果

    # re: AJAX從服務端獲取數據的三種方法  回復  更多評論   

    并不是所有的html標簽的innerHTML都有bug。我碰到的是<select>標簽的innerHTML有一些bug。

    不信通過getElementById獲得<select>對象后,使用下面的代碼試試,看看會發生什么效果

    var select = getElementById("selectid");
    select.innerHTML = "<option>abc</option><option>ddd</option>";

    上面的代碼是出不來的選項的,不知怎么著,IE6把第一個<option>弄沒了。
    只有用下面的代碼才好使:


    var select = getElementById("selectid");
    select.outerHTML = "<select id='selectid' ><option>abc</option><option>ddd</option></select>";
    2008-05-27 08:49 | 銀河使者

    # re: AJAX從服務端獲取數據的三種方法  回復  更多評論   

    你試試重裝一下你的軟件看看能不能正常,樓主
    2008-05-27 17:58 | 懶人

    # re: AJAX從服務端獲取數據的三種方法  回復  更多評論   

    重裝軟件可是最后一招。 這最后一招殺手锏我可不想這么快就用。 還是研究一下vs2008的設計視圖為什么不好使吧。要是一不好使就重裝,那不是要把人弄瘋了。vs2008很大的,如果重裝還不行,是不是要重裝xp啊。^-^
    2008-05-27 21:58 | 銀河使者

    # re: AJAX從服務端獲取數據的三種方法  回復  更多評論   

    @銀河使者
    思路不錯,不過是不是安裝的時候哪個選項給漏掉了
    2008-05-29 11:04 | 懶人

    # re: AJAX從服務端獲取數據的三種方法  回復  更多評論   

    我一般安裝任何軟件都是完全安裝的,沒辦法,硬盤就是大。^-^,要說漏掉是不可能的,我都是全選的。單位的機器也是按著同樣的方法安的,沒有問題,就是家里的dell筆記本出這種事。昨天安了個vs2008的patch,也不好使。
    2008-05-29 12:39 | 銀河使者

    # re: AJAX從服務端獲取數據的三種方法  回復  更多評論   

    ajax不就是后臺發送請求,接收返回的結果,然后解析,不是嗎?
    2008-05-29 18:15 | stanley_xu

    # re: AJAX從服務端獲取數據的三種方法  回復  更多評論   

    ajax從原理上講很簡單。其實任何技術從基本原理上看都很簡單。但實現起來,確是另外一回事。
    2008-05-29 18:45 | 銀河使者

    # re: AJAX從服務端獲取數據的三種方法  回復  更多評論   

    LZ說的是,實現起來的感覺.......
    現在的AJAX框架技術太多了,搞得我不知用哪種好,唉!
    2008-05-30 16:00 | hulu

    # re: AJAX從服務端獲取數據的三種方法  回復  更多評論   

    只要適合自己的,就是好的。
    2008-05-30 20:45 | 銀河使者

    # re: AJAX從服務端獲取數據的三種方法[未登錄]  回復  更多評論   

    下次能不能寫全了再給放上來,文章代碼內容不全,讓我調試了半天才搞定。
    2008-07-19 19:39 | eric

    # re: AJAX從服務端獲取數據的三種方法  回復  更多評論   

    本文的只是代碼片段,為了演示這個功能,本文已經假設讀者對javascript比較熟悉,因此,并沒有列出所有的代碼。如果那么,會無法突出重點,讓想看這部分內容的讀者不容易找到了。在以后的文章,我會提供源代碼供讀者下載學習。謝謝關注本文。
    2008-07-19 19:51 | 銀河使者

    # re: AJAX從服務端獲取數據的三種方法  回復  更多評論   

    JSON更爽.
    2008-07-28 18:37 | Beniao

    # re: AJAX從服務端獲取數據的三種方法  回復  更多評論   

    json里面這些都自動處理了,請看我的這篇文章
    http://www.tkk7.com/nokiaguy/archive/2008/07/04/212515.html
    2008-07-28 20:34 | 銀河使者

    # re: AJAX從服務端獲取數據的三種方法  回復  更多評論   

    i8里面第二個select選擇的時候就沒有了。不知道是怎么回事。我用的outerHTML
    2009-03-24 22:50 | liuhua

    # re: AJAX從服務端獲取數據的三種方法  回復  更多評論   

    @liuhua
    我在ie6下測的,it7和ie8沒測過,也許是不兼容的問題吧。哎~
    2009-03-25 08:27 | 銀河使者
    主站蜘蛛池模板: 免费无码一区二区三区| 国产成人A人亚洲精品无码| 最近中文字幕国语免费完整| 一区二区三区免费在线视频 | 亚洲精品国产专区91在线| 国产亚洲色婷婷久久99精品91| 成年女人视频网站免费m| 一级毛片免费毛片一级毛片免费| 九九全国免费视频| 亚洲AV无码一区二区一二区| 亚洲欧洲日产国码二区首页| 亚洲av无码成人黄网站在线观看| 在线亚洲97se亚洲综合在线| 免费a级毛片无码av| 日韩视频在线免费观看| 四虎影院免费在线播放| 国产v精品成人免费视频400条| 99re这里有免费视频精品| 免费看少妇高潮成人片| 中文字幕在线免费观看视频| 成人精品综合免费视频| 羞羞视频在线免费观看| 国产成人亚洲毛片| 亚洲av无码有乱码在线观看| 亚洲AV无码国产精品永久一区| 精品国产日韩久久亚洲| 涩涩色中文综合亚洲| 亚洲成A人片在线播放器| 亚洲AV无码专区在线亚| 亚洲综合色区中文字幕| 亚洲人成77777在线播放网站不卡| 亚洲国产精品午夜电影| 亚洲一卡2卡4卡5卡6卡残暴在线| 亚洲熟妇色自偷自拍另类| 亚洲欧洲日产韩国在线| 亚洲a级在线观看| 亚洲人成网站18禁止| 久久亚洲精品11p| 搜日本一区二区三区免费高清视频 | 日日摸日日碰夜夜爽亚洲| 亚洲国产综合AV在线观看|