欧美成人精品手机在线观看_69视频国产_动漫精品第一页_日韩中文字幕网 - 日本欧美一区二区

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

AJAX從服務(wù)端獲取數(shù)據(jù)的三種方法

admin
2013年7月11日 22:43 本文熱度 5663

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

方法一、從服務(wù)端獲得XML格式的數(shù)據(jù)

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

// 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函數(shù)將在XMLHttpRequest對象的異步訪問服務(wù)端時調(diào)用。當(dāng)readyState4時表示成功從服務(wù)端返回XML數(shù)據(jù)。這個函數(shù)的實現(xiàn)代碼如下:

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

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

    getData函數(shù)負(fù)責(zé)向服務(wù)端發(fā)送請求,并設(shè)置異步事件。實現(xiàn)代碼如下:

function getData(url, selectId)
{
    
var myRequest = getXMLHTTPRequest();  // 獲得一個XMLHttpRequest對象
    
    
if(myRequest)
    {
        myRequest.onreadystatechange 
=  function() // 接收獲得數(shù)據(jù)狀態(tài)的事件函數(shù)
        {                        
            onReadyState(myRequest, selectId);  
        }
         
        
try 
        {
            myRequest.open( 
"post", url, true);
            
        }
        
catch(e)
        {
            alert(e);
        } 
        
try
        {

            myRequest.send(
"");
  
        }
        
catch(e)
        {
            alert(e);
        }
  
    }
}

   現(xiàn)在本例子的核心代碼已經(jīng)實現(xiàn)完成,下一步就是在html而加載時從服務(wù)端獲得第1<select>標(biāo)簽的數(shù)據(jù),并將其加載到第1<select>標(biāo)簽中。讓我們先看一下這個靜態(tài)的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>標(biāo)簽分別是bigKindsmallKind,里面并沒有<option>標(biāo)簽,這是因為<option>標(biāo)簽要在javascript里動態(tài)加載。下面我們先來加載bigKind中的數(shù)據(jù)。

window.onload = onLoad
function onLoad()
{                         

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


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

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方法中都可以看出,首先會獲得請求參數(shù)kind,如果這個參數(shù)不存在,則返回bigKind所需要的數(shù)據(jù),以xml格式返回,類似于如下的格式:

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


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

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(
"手機(jī)");
        eProducts.add(
"數(shù)碼/IT");
        eProducts.add(
"家電");
        eProducts.add(
"電腦");
                
        data.put(
"消費(fèi)電子", 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(
"經(jīng)濟(jì)");
        books.add(
"法律");
        books.add(
"計算機(jī)");
        books.add(
"英語");
        books.add(
"通訊");
        books.add(
"其他");
        
        data.put(
"圖書", books)        ;                        
    }
}


    其中data變量中的key值就是bigKind中的值,而每一個key對應(yīng)的值(一個List<String>對象就是smallKind中值的列表)。下面我們來實現(xiàn)當(dāng)?shù)?/span>1<select>標(biāo)簽bigKind變化時,更新smallKind標(biāo)簽。<select>的onchange事件函數(shù)的代碼如下:

function onChange(obj)
{
    
try
    {
        getData(encodeURI(encodeURI(
"../GetXML?kind=" +obj.options[obj.selectedIndex].value)), "smallKind");
     
    }
    
catch(e)
    {
        alert(e);
    }
}

    這個函數(shù)是<select>標(biāo)簽的onchange事件函數(shù)。obj表示<select>標(biāo)簽本身。這個函數(shù)中只有一條有實際意義的語句,也就是調(diào)用了getData方法,這個方法人在onLoad方法中調(diào)用getData時差不多,只是在傳送url時使用了兩個encodeURI方法。由于XMLHttpRequest方法以utf-8向服務(wù)端發(fā)送數(shù)據(jù),因此,要使用兩個encodeURI向服務(wù)端發(fā)送%xx形式的utf-8編碼,然后在服務(wù)端進(jìn)行解析。我們在GetXML中的processRequest方法中可以找到如下的一條語句:

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

 

    就是進(jìn)行解碼操作。

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

方法二、直接獲得<option>...</option>內(nèi)容的字符串

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

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

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

方法三、從服務(wù)端返回javascript代碼,在客戶端使用eval函數(shù)執(zhí)行

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

    var options = new Array();

    options.push(‘data1’);

    options.push(‘data2’);

    然后使用eval函數(shù)執(zhí)行上面的字符串,這樣我們在javascript中就可以使用options數(shù)組了。我個人認(rèn)為,使用數(shù)組要比使用XMLDocument更容易,代碼量也更少。如果要返回更為復(fù)雜的數(shù)據(jù),也可以使用javascript中的類或其他數(shù)據(jù)結(jié)構(gòu)。根據(jù)上面的思想,新的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();
        }
    }

    客戶端經(jīng)過改進(jìn)的addOptions函數(shù)如下:

// javascript表示從服務(wù)端返回的javascript代碼字符串
function addOptions(select, javascript)
{    
    
if(select)
    {   
        
if(select.id == "smallKind")
        {
            
if(isIE())
                select.options.length 
= 0
        }
        
var myOptions = "";
        eval(javascript);  
//執(zhí)行從服務(wù)端返回的javascript代碼
        for(var i = 0; i < options.length ; i++)  // 從options數(shù)組中取數(shù)據(jù)
        {             
            
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數(shù)組來添加選擇項,而不是使用outerHTML。這么做的好處是可以在onLoad方法中就獲得<select>的選項值。而如果使用outerHTMLhtml未裝載完時,<select>標(biāo)簽中選擇項仍然為0。這樣在onLoad方法中就無法訪問<select>中的被加入項了,當(dāng)然,在onchange事件中可以。 

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



                               圖1

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


該文章在 2013/7/11 22:43:12 編輯過
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點晴ERP是一款針對中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內(nèi)大量中小企業(yè)的青睞。
點晴PMS碼頭管理系統(tǒng)主要針對港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場、車隊、財務(wù)費(fèi)用、相關(guān)報表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點,圍繞調(diào)度、堆場作業(yè)而開發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點晴WMS倉儲管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號管理軟件。
點晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時間、不限用戶的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved