html頁面的局部刷新


      有時候我們在做一個動態/靜態網頁,網頁中的某部分需要從服務器獲取值但是不能把整個頁面都提交到服務器,也就是要對頁面做局部刷新,也就是對整個網頁無刷新更新值。在這種情況下就需要用JS和XMLHttpRequest對象的配合實現,本片文章記錄怎樣才能做到整張網頁的局部刷新以備日后回顧。

文章分為兩部分:XMLHTTPRequest介紹;用XMLHTTPRequest和JavaScript實現局部刷新。

第一部分

我們了解一下XMLHTTPRequest。

XMLHTTPRequest對象可以在不向服務器提交整個頁面的情況下,實現局部更新網頁。當頁面全部加載完畢后,客戶端通過該對象向服務器請求數據,服務器端接受數據並處理后,向客戶端反饋數據。 XMLHttpRequest 對象提供了對 HTTP 協議的完全的訪問,包括做出 POST 和 HEAD 請求以及普通的 GET 請求的能力。XMLHttpRequest 可以同步或異步返回 Web 服務器的響應,並且能以文本或者一個 DOM 文檔形式返回內容。

使用XMLHTTPRequest的時候我們不用太關心瀏覽器支持的問題。實際上,XMLHTTPRequest得到了所有現代瀏覽器較好的支持。唯一的瀏覽器依賴性涉及XMLHTTPRequest對象的創建。在IE5和IE6中,必須試用IE特定的ActiveXObject() 構造函數才能創建,但是現在還有多少人在用IE5和IE6呢?。。。

簡單了解什么是XMLHTTPRequest之后,我們看一下怎么創建XMLHTTPRequest對象。

不同的瀏覽器要使用不同的方法創建XMLHTTPRequest對象:IE用ActiveObject創建,其它的瀏覽器用名為XMLHttpRequest的JavaScript內建對象。貌似看起來創建一個所有瀏覽器都支持的XMLHTTPRequest有點復雜,不過我們可以用以下簡單的代碼創建:

var XMLHttp=null;//創建變量XMLHttp,作為XMLHTTPRequest對象

if (window.XMLHttpRequest)//針對除IE之外的瀏覽器做判斷,看是否能創建XMLHTTPRequest

{

XMLHttp=new XMLHttpRequest()//能的話就直接創建

}else if (window.ActiveXObject)

{

XMLHttp=new ActiveXObject("Microsoft.XMLHTTP")//如果不能,就是IE了,用ActiveXObject創建

}

以上代碼中,在判斷IE處使用了傳入Microsoft.XMLHTTP這個參數創建XMLHTTPRequest對象,這個方法適用於IE5.5及更高版本,但是不是創建XMLHTTPRequest對象最快的方法,我們看改進后的:

 

function GetXmlHttpObject()

{

var xmlHttp=null;

try {

// 針對Firefox, Opera 8.0+, Safari瀏覽器創建

xmlHttp=new XMLHttpRequest();

}

catch (e)

{

// 不行的話就是IE了

try {

xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");//這個是最快的

}

catch (e) {

xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");//為了以防萬一,如果錯誤后我們再用慢的方式

}

}

return xmlHttp;

}

上面這段代碼,在對IE的判斷上我們用XMLHttp=new ActiveXObject("Msxml2.XMLHTTP")創建,這在IE6+版本可用,如果錯誤,則用適合IE5.5的老方法創建。

知道了怎樣創建后,我們看一下XMLHTTPRequest的屬性。

XMLHTTPRequest有5個屬性:readyState、responseText、responseXML、status、statusText。

readyState

這是HTTP請求的狀態,值有5個,初次創建XMLHTTPRequest時是0,直到HTTP響應結束,這個值一直增加到4。這5個狀態的名稱和含義如下表:

 

 

狀態

名稱

描述

0

Uninitialized

初始化狀態。XMLHttpRequest 對象已創建或已被 abort() 方法重置。

1

Open

open() 方法已調用,但是 send() 方法未調用。請求還沒有被發送。

2

Send

Send() 方法已調用,HTTP 請求已發送到 Web 服務器。未接收到響應。

3

Receiving

所有響應頭部都已經接收到。響應體開始接收但未完成。

4

Loaded

HTTP 響應已經完全接收。

 

這里要說明一下,readyState的值不會遞減,除非在請求的過程中調用了abort() 或 open() 方法。每次值增加的時候都會觸發onreadystatechange事件。

responseText

到目前為止從服務器接收到的響應體(不包括頭部)。如果還沒有接收到數據的話,就是空字符串。

根據上一個屬性,我們可以知道,當readyState值為3之前,responseText的值都為空,直到為4的時候,才是這個屬性保存了完整的HTTP響應體。

responseXML

對請求的響應,解析為 XML 並作為 Document 對象返回。如果響應體不是“text/xml”返回null。

Status

由服務器返回的 HTTP 狀態代碼,如 200 表示成功,而 404 表示 "Not Found" 錯誤。當 readyState 小於 3 的時候讀取這一屬性會導致一個異常。

statusText

這個屬性用名稱而不是數字指定了請求的 HTTP 的狀態代碼。也就是說,當狀態為 200 的時候它是 "OK",當狀態為 404 的時候它是 "Not Found"。和 status 屬性一樣,當 readyState 小於 3 的時候讀取這一屬性會導致一個異常。

以上是XMLHTTPRequest的屬性,接下來,我們看一下它的方法。

XMLHTTPRequest對象的方法有6個:abort()、getAllResponseHeaders()、getResponseHeader()、open()、send()、setRequestHeader()

abort()

這個方法是取消當前響應,關閉與服務器的連接並結束任何發生或沒有發生的網絡活動。

一旦調用了這個方法,XMLHttpRequest對象會重置readState為0,一般會用在請求時間過長,響應不再必要的時候。

 

getAllResponseHeaders()

把 HTTP 響應頭部作為未解析的字符串返回。

如果 readyState 小於 3,這個方法返回 null。否則,它返回服務器發送的所有 HTTP 響應的頭部。頭部作為單個的字符串返回,一行一個頭部。每行用換行符 "" 隔開。

getResponseHeader()

返回指定的 HTTP 響應頭部的值。其參數是要返回的 HTTP 響應頭部的名稱。可以使用任何大小寫來制定這個頭部名字,和響應頭部的比較是不區分大小寫的。

該方法的返回值是指定的 HTTP 響應頭部的值,如果沒有接收到這個頭部或者 readyState 小於 3 則為空字符串。如果接收到多個有指定名稱的頭部,這個頭部的值被連接起來並返回,使用逗號和空格分隔開各個頭部的值。

open()

此方法是初始化HTTP請求參數,比如URL和HTTP的請求方法(get,post等)。

send()

試用傳遞給open()方法的參數發送HTTP請求。

setRequestHeader()

向一個打開但未發送的請求設置或添加一個 HTTP 請求。

以上便是XMLHTTPRequest的所有方法,如果看到這里不太累的話,下面我們了解一下open()和send()方法怎么用。

XMLHttpRequest.open()

初始化 HTTP 請求參數

語法

open(method, url, async, username, password)method 參數是用於請求的 HTTP 方法。值包括 GET、POST 和 HEAD。

url 參數是請求的主體。大多數瀏覽器實施了一個同源安全策略,並且要求這個 URL 與包含腳本的文本具有相同的主機名和端口。

async 參數指示請求使用應該異步地執行,值為true和false。如果這個參數是 false,請求是同步的,后續對 send() 的調用將阻塞,直到響應完全接收。如果這個參數是 true 或省略,請求是異步的,且通常需要一個 onreadystatechange 事件句柄。

username 和 password 參數是可選的,為 url 所需的授權提供認證資格。如果指定了,它們會覆蓋 url 自己指定的任何資格。

說明

這個方法初始化請求參數以供 send() 方法稍后使用。它把 readyState 設置為 1,刪除之前指定的所有請求頭部,以及之前接收的所有響應頭部,並且把 responseText、responseXML、status 以及 statusText 參數設置為它們的默認值。當 readyState 為 0 的時候(當 XMLHttpRequest 對象剛創建或者 abort() 方法調用后)以及當 readyState 為 4 時(已經接收響應時),調用這個方法是安全的。當針對任何其他狀態調用的時候,open() 方法的行為是為指定的。

除了保存供 send() 方法使用的請求參數,以及重置 XMLHttpRequest 對象以便復用,open() 方法沒有其他的行為。要特別注意,當這個方法調用的時候,實現通常不會打開一個到 Web 服務器的網絡連接。

XMLHttpRequest.send()

發送一個 HTTP 請求

語法

send(body)如果通過調用 open() 指定的 HTTP 方法是 POST 或 GET,body 參數指定了請求體,作為一個字符串或者 Document 對象。如果請求體不是必須的話,這個參數就為 null。對於任何其他方法,這個參數是不可用的,應該為 null(有些實現不允許省略該參數)。

說明

這個方法導致一個 HTTP 請求發送。如果之前沒有調用 open(),或者更具體地說,如果 readyState 不是 1,send() 拋出一個異常。否則,它發送一個 HTTP 請求,該請求由以下幾部分組成:

之前調用 open() 時指定的 HTTP 方法、URL 以及認證資格(如果有的話)。 之前調用 setRequestHeader() 時指定的請求頭部(如果有的話)。 傳遞給這個方法的 body 參數。 一旦請求發布了,先觸發 onreadystatechange 事件句柄,隨后send() 把 readyState 設置為 2,並觸發 onreadystatechange 事件句柄。

如果之前調用的 open() 參數 async 為 false,這個方法會阻塞並不會返回,直到 readyState 為 4 並且服務器的響應被完全接收。否則,如果 async 參數為 true,或者這個參數省略了,send() 立即返回,並且正如后面所介紹的,服務器響應將在一個后台線程中處理。

如果服務器響應帶有一個 HTTP 重定向,send() 方法或后台線程自動遵從重定向。當所有的 HTTP 響應頭部已經接收,send() 或后台線程把 readyState 設置為 3 並觸發 onreadystatechange 事件句柄。如果響應較長,send() 或后台線程可能在狀態 3 中觸發 onreadystatechange 事件句柄:這可以作為一個下載進度指示器。最后,當響應完成,send() 或后台線程把 readyState 設置為 4,並最后一次觸發事件句柄。

第二部分

用XMLHttpRequest對象和JavaScript做網頁局部刷新

我們以無動態刷新省市級聯為例來做頁面的局部刷新。假定,在某一個活動報名的頁面(默認.net平台)上需要錄入用戶的信息,比如省市、姓名、性別、電話號碼、郵箱等信息。在這個報名表單中,我們把選擇省市處做成下拉菜單。如果這個頁面用自動回發,用戶在每選擇一次省份的時候頁面就會刷新一次,肯定會降低用戶體驗,我們把它做成無刷新的方式,XMLHTTPRequest對象會默默無聞的向服務器請求數據,不打擾用戶,用戶在頁面停留的平均時間也會延長,體驗會更好。

下面我們就用第一部分介紹的XMLHTTPRequest對象實現局部刷新。

首先,我們實例化一個XMLHTTPRequest對象:

// JavaScript Document

function GetXMLHttpRequest()

        {

            var xmlhttp=null;

            try

            {

                xmlhttp =new ActiveXObject("Msxml2.XMLHTTP");

            }

            catch(e)

            {

                try

                {

                    xmlhttp =new ActiveXObject("Microsoft.XMLHTTP");

                }

                catch(oc)

                {

                    xmlhttp =null;

                }

            }

            if(!xmlhttp && typeof XMLHttpRequest != "undefined")

            {

                xmlhttp =new XMLHttpRequest();

            }

            return xmlhttp;

        }

然后,封裝一個獲取服務器數據的JS函數:

function GetServerData(obj) {

            var FValue = obj.value;//傳過來的值,可以作為一個參數傳入數據接口。

            var weburl = "http://www.example.com/index.ashx?provinceid=" + FValue;//請求的url地址,這個地址僅為示例,實際不存在

            var xmlhttp = GetXMLHttpRequest();//實例化XMLHTTPRequest            xmlhttp.open("get",weburl,true);//調用open()方法      xmlhttp.onreadystatechange=function()//readyState 屬性改變的時候調用的事件句柄函數

            {

                if(xmlhttp.readyState==4)//服務器已經成功返回數據

                {

var result=xmlhttp.responseText; //得到服務器返回的數據,然后怎么處理這些數據,看你的了

                }

            }

            xmlhttp.send(null);

        }

到這里,網頁的局部刷新的最關鍵的部分就完成了,剩下的就是根據具體的需要操作服務器返回的數據了。

如果看到這里還是有點不懂,看一下下面的這個小例子,以下是源碼

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="NoRefresh.aspx.cs" Inherits="WebApplication1.NoRefresh" %>

 

<!DOCTYPE html>

 

<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">

<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>

    <title>頁面局部刷新</title>

    <script type="text/javascript">

        function GetXMLHttpRequest() {

            var xmlhttp = null;

            try {

                xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");

            }

            catch (e) {

                try {

                    xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");

                }

                catch (oc) {

                    xmlhttp = null;

                }

            }

            if (!xmlhttp && typeof XMLHttpRequest != "undefined") {

                xmlhttp = new XMLHttpRequest();

            }

            return xmlhttp;

        }

        function GetServerData(obj) {

            var FValue = obj.value;

            var weburl =  "http://www.example.com/index.ashx?provinceid=" + FValue; //請求的url地址,這個地址僅為示例,實際不存在

            var xmlhttp = GetXMLHttpRequest();

            xmlhttp.open("get", weburl, true);

            xmlhttp.onreadystatechange = function () {

                if (xmlhttp.readyState == 4) {

                    //得到服務器返回的數據

                    var result = xmlhttp.responseText;

                    document.getElementById("<%=ddl_city.ClientID %>").length = 0;

                    document.getElementById("<%=ddl_city.ClientID %>").options.add(new Option("請選擇城市", "0"));

                    if (result != "") {

                        var cityArry = eval("(" + result + ")");//string --> object這里我們模擬獲取的數據是JSON數組。切記,從服務器上獲取的JSON數組一定要轉換為object數據類型,否則無法獲取值。

                        for (var i = 0; i < cityArry.City.length; i++) {

                            var cityid = cityArry.City[i].CityID;

                            var cityname = cityArry.City[i].CityName;                            document.getElementById("<%=this.ddl_city.ClientID %>").options.add(new Option(cityname, cityid));

                        }

                    }

                }

            }

            xmlhttp.send(null);

        }

    </script>

</head>

<body style="background:url('images/bodybg.png') repeat top;">

    <form id="form1" runat="server">

    <div style="width:200px; height:100px; margin-top:50px; margin-left:100px;">

        省份:<asp:DropDownList ID="ddl_province" runat="server" onchange="GetServerData(this)">

            <asp:ListItem Value="0">請選擇省份</asp:ListItem>

            <asp:ListItem Value="1">北京</asp:ListItem>

            <asp:ListItem Value="16">河南</asp:ListItem>

           </asp:DropDownList><br />

        城市:<asp:DropDownList ID="ddl_city" runat="server">

            <asp:ListItem Value="0">請選擇市區</asp:ListItem>

           </asp:DropDownList>

    </div>

    </form>

</body>

</html>

 另:頁面用到的JSON數組

{"City":[{"CityID":"152","CityName":"鄭州市"},{"CityID":"153","CityName":"開封市"},{"CityID":"154","CityName":"洛陽市"},{"CityID":"155","CityName":"平頂山市"},{"CityID":"156","CityName":"安陽市"},{"CityID":"157","CityName":"鶴壁市"},{"CityID":"158","CityName":"新鄉市"},{"CityID":"159","CityName":"焦作市"},{"CityID":"160","CityName":"濮陽市"},{"CityID":"161","CityName":"許昌市"},{"CityID":"162","CityName":"漯河市"},{"CityID":"163","CityName":"三門峽市"},{"CityID":"164","CityName":"南陽市"},{"CityID":"165","CityName":"商丘市"},{"CityID":"166","CityName":"信陽市"},{"CityID":"167","CityName":"周口市"},{"CityID":"168","CityName":"駐馬店市"}]}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM