ajax|asp+|重新整理|無重新整理
不知上過ChinaRen校友錄的朋友們有沒有注意,ChinaRen在改版後很多方面都進行了較大的改動。例如留言與回複方面已經不再像以前那樣,在每次提交後總得重新載入一下整個頁面,碰到網速超慢時,只能幹瞪著眼睛等待。那麼現在這種炫麗的效果又是如何做到的呢,如果你覺得有興趣,那就跟著我一起往下看吧!
瞭解Ajax的朋友也許知道其實這種炫麗效果的實現並不是一件很為難的事,當然如果你不瞭解何為Ajax那也沒有關係,本節我們就通過打造一個新聞評論系統,來看看到底什麼是Ajax,首先我們還是先瞭解一些基礎東西。
什麼是Ajax?
Ajax提出者Jesse James Garrett在《Ajax:一個Web應用的新途徑》中提到Ajax為“Asynchronous JavaScript + XML”的簡稱,也就是非同步JavaScript和XML處理。其包含:
用XHTML和CSS進行基於標準的表示方式:
採用DOM(document object model)動態顯示和互動操作;
採用XML和XSLT進行資料交換和操作;
採用XMLHttpRequest進行非同步資料擷取;
採用JavaScript綁定上述技術應用;
Ajax與傳統Web應用有什麼不同?
Ajax與傳統Web應用最大的不同就是Ajax可以對頁面某一個地區進行局部載入,而不是像傳統Web中每次頁面請求後的都必須重新載入整個頁面,特別在頁面負載比較大的情況下,頁面載入時間就比較長,使用者多數時間就處在等待狀態,而呈現給使用者的僅僅是一片空白,而在Ajax的應用中就可以很好的避免這類事情的發生。
Ajax的工作原理是什麼?
Ajax主要是通過JavaScript對象中的XmlHttpRequest向伺服器提出請求,並根據處理的結果更新頁面。這樣的更新不會使整個頁面全部更新,而是根據使用者的需要對某個地區進行局部更新,而且在更新的同時不影響其它地區的瀏覽。例如:搜狐個人部落格中每個欄目後面的重新整理按鈕。
什麼是XmlDom?
XMLDOM是用來訪問和操作XML文檔的編程介面規範。XMLDOM被設計為可用於任何語言和任何作業系統。藉助DOM,程式員可以建立XML文檔、遍曆其結構,增、改、刪其元素。DOM將整個XML文檔視作一棵樹,文檔級的元素是樹的根。
下面我們就來看看幾個與本教程相關的功能,值得注意的是以下方法或屬性並不是同一個對象下,具體請看說明:
getElementsByTagName 方法
說明:傳回指定名稱的元素集合。
文法:objNodeList = xmlDocument.getElementsByTagName(tagname);
例:var node=xmlDom.responseXML.getElementsByTagName("pl");
getAttribute()方法
說明:獲得某個元素節點的屬性值
文法:elementNode.getAttribute(name)
例:var tot=xmlDom.responseXML.getElementsByTagName("pl")[0].getAttribute("tot");
childNodes 屬性
說明:傳回一個節點列表,包含該節點所有可用的子節點。
文法:objNodeList=node.childNodes;
例:objNodeList = xmlDoc.childNodes;
如需具體的某一個節點, var u= xmlDoc.childNodes(0);
Length屬性 ()
說明:返回一個節點列表中的節點數量
文法:nodelistObject.length
例:var len=node.length;
至此,基礎知識已經講完了,如果你還是不太瞭解的話,那建議你去看一些javascript相關的教程。下面我們就看這個新聞評論系統的具體實現原理
假設有一個頁面index.asp,上半部分為評論列表顯示地區,下面為評論提交地區。那麼這樣一個頁面我們如何顯示評論內容和提交評論呢?
傳統:上半部分評論列表直接通過資料庫查詢語句讀取並顯示,每當提交新的評論時,先傳遞給處理頁面,處理頁面處理完畢後再返回index.asp這個頁面,當然index.asp是重新載入獲得新的評論。
Ajax::首先列表頁面的內容是一個單獨的xml檔案(pl_list.asp),然後index..asp中的上半部分評論通過XmlHttpRequest請求pl_list.asp頁面,並通過返回的結果傳遞到需要更新地區。提交評論同樣如此,每次提交採用XmlHttpRequest請求提交處理常式,然後重新更新評論列表顯示地區。
此新聞評論系統共分為五個部分,分別為資料庫、前台頁面、JS代碼、伺服器處理、CSS樣式。
資料庫的設計
PL表:
欄位名
類型
長度
id
自動編號
user
文本
20
dateandtime
日期/時間
content
備忘
newid
數字
前台頁面:(index.htm)
如上圖所示,前台頁面共包括兩部分,上半部分為頁面評論列表顯示,下半部分為提交評論。由於我們這裡只是類比一個新聞評論系統,並沒有真正的新聞頁面,那麼在傳遞新聞ID的時候我們採用了一個預設值 〈input name="newsid" value="1" type="hidden"/〉。
代碼:index.htm
〈%@LANGUAGE="VBSCRIPT" CODEPAGE="936"%〉
〈!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〉
〈meta http-equiv="Content-Type" content="text/html; charset=gb2312" /〉
〈title〉評論系統〈/title〉
〈script src="main.js"〉〈/script〉
〈link href="main.css" rel="stylesheet" type="text/css" /〉
〈/head〉
〈body〉
〈div id="pllist"〉正在載入評論……
〈script〉 loadDom();setTimeout("loadDom()",10000);〈/script〉
〈/div〉
〈div style="width:240px;font-size:12px;text-align:center"〉
〈fieldset〉〈legend〉評論〈/legend〉
呢稱:〈input name="user" type="text" style="width:180px"/〉〈input name="newsid" value="1" type="hidden"/〉〈br/〉
內容:〈textarea name="content" style="width:180px;height:80px"〉〈/textarea〉〈br/〉
〈input name="submit" value="我要評論" type="button" /〉
〈/fieldset〉
〈/div〉
〈div style="font-size:12px;" id="msg"〉
〈/div〉
〈/body〉
〈/html〉
JS字碼頁(核心部分) main.js
JS代碼算是本系統的一個核心部分了,Ajax的體現基本全包含在這短短數十行的代碼中,是連結前台與幕後處理的一個橋樑,可謂是重中之重,為了更好的讓大家理解整個功能,我們將分段介紹。
1、獲得XmlHttp對象,建立並返回一個XmlHttp對象。
var xhr;
function getXHR()
{
try {
xhr=new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
xhr=new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
xhr=false;
}
}
if(!xhr&&typeof XMLHttpRequest!='undefined')
{
xhr=new XMLHttpRequest();
}
return xhr;
}
function openXHR(method,url,callback)
{
getXHR();
xhr.open(method,url);
xhr.onreadystatechange=function()
{
if(xhr.readyState!=4)return;
callback(xhr);
}
xhr.send(null);
}
function loadXML(method,url,callback)
{
getXHR();
xhr.open(method,url);
xhr.setRequestHeader("Content-Type","text/xml");
xhr.setRequestHeader("Content-Type","GBK");
xhr.onreadystatechange=function()
{
if(xhr.readyState!=4)return;
callback(xhr);
}
xhr.send(null);
}
具體的調用方法:
loadXML(method,url,callback)
method: http方法,例如:POST、GET、PUT及PROPFIND
url: 請求的URL地址,可以為絕對位址也可以為相對位址
callback:自訂的返回處理函數
2.獲得評論列表
此段代碼的主要功能是根據伺服器處理返回的資訊更新前台頁面的內容,主要包括顯示評論列表、評論列表分頁、跳轉頁數三個功能。
顯示評論列表:getList函數
function getList(xmlDom)
{
var pllist=document.getElementById("pllist"); //獲得頁面pllist對象,此對象用來顯示評論內容
var node=xmlDom.responseXML.getElementsByTagName("pllist");//獲得pllist節點集合
var tot=xmlDom.responseXML.getElementsByTagName("pl")[0].getAttribute("tot");//獲得pl節點tot屬性值,這裡指評論的總數量
var curpage=xmlDom.responseXML.getElementsByTagName("pl")[0].getAttribute("curpage");//獲得pl節點curpage屬性,這裡指評論列表當前所在的頁數,應用於翻頁
if (tot!=0) //判斷當前評論數是否為空白
{
var cont="";
var len=node.length;//獲得pllist節點集合中節點的總數量
for(var i=0;i〈len;i++)
{
var u=node[i].childNodes(0).text;//獲得節點第一個子節點的值,這裡指呢稱
var d=node[i].childNodes(1).text; //獲得節點第二個子節點的值,這裡指時間
var co=node[i].childNodes(2).text; //獲得節點第三個子節點的值,這裡指內容
var idnub=node[i].childNodes(3).text; //獲得節點第四個子節點的值,這裡指新聞ID
cont+='〈div class="u"〉呢稱:'+u+'〈/div〉〈div class="d"〉時間:'+d+'〈/div〉〈div class="idnub" style="cursor:hand" onmousemove="this.style.background=\'#99cc66\'"〉刪除〈/div〉〈div class="co"〉內容:'+co+'〈/div〉'; //將所獲得的評論內容產生一個字串
}
var cont1=pagecount(tot,curpage);//調用分頁函數
cont+=cont1;
pllist.innerHTML=cont;//將內容呈現
}
else
{
pllist.innerHTML="暫無評論!";
}
}
評論列表分頁:pagecount函數
function pagecount(tot,cur)
{
var cont1="";
if (tot%5==0) //預設每頁五條,這個要求與伺服器端保持一致
{
pages=parseInt(tot/5);
}
else
{
pages=parseInt(tot/5)+1;
}
for(var j=1;j〈=pages;j++)
{
if (j==cur)
{ cont1+="〈span〉"+j+"〈/span〉 "}
else
{ cont1+="〈span style='cursor:hand;color:#0000ff' onmouseout='this.style.background=\"\"' onmousemove='this.style.background=\"#99cc66\"' onclick='gotopage("+j+")'〉"+j+"〈/span〉 "}
}
return cont1;
}
跳轉頁數:gotopage函數
function gotopage(page)
{
loadXML("get","pl_list.asp?page="+page,getList);
}
function loadDom() //定時更新評論列表,初始化10秒鐘
{
loadXML("get","pl_list.asp",getList);
setTimeout("loadDom()",10000)
}
3.刪除評論
function del(idnub)
{
var msg=document.getElementById("msg");
msg.innerText="正在刪除……";
loadXML("get","pl_del.asp?id="+idnub,getdel);
}
function getdel(xmlDom) //刪除後所觸發的事件,更新頁面
{
var msg=document.getElementById("msg");
msg.innerText="刪除成功!";
loadXML("get","pl_list.asp",getList);
}
4.提交評論
function fb() //處理提交
{
var msg=document.getElementById("msg");
var user=document.getElementById("user");
var content=document.getElementById("content")
var newsid=document.getElementById("newsid")
if (user.value=="")
{
alert("呢稱不可為空白!");
return false;
}
if (content.value=="")
{
alert("內容不可為空白!");
return false;
}
msg.innerText="正在發表評論";
loadXML("get","pl_fb.asp?user="+user.value+"&content="+content.value+"&newsid="+newsid.value,getfb);
}
function getfb(xmlDom) //評論提交後所觸發的事件,更新評論列表
{
var msg=document.getElementById("msg");
msg.innerText=xmlDom.responseText;
loadXML("get","pl_list.asp",getList);
}
伺服器處理常式
根據JS字碼頁的分段介紹,我們瞭解此系統的功能大致包括評論的顯示處理、評論的刪除處理、評論的提交處理三個功能,那麼我們就根據這三個功能分別介紹。
評論的顯示處理頁面:pl_list.asp
此程式為asp產生xml檔案,通過分頁的方式將評論的內容以XML的形式呈現出來,我們可以單獨運行。
代碼:
〈!--#include file="conn.asp"--〉
〈%
Response.ContentType = "text/XML"
Response.expires = 0
Response.expiresabsolute = Now() - 1
Response.addHeader "pragma", "no-cache"
Response.addHeader "cache-control", "private"
Response.CacheControl = "no-cache"
Response.write("〈?xml version=""1.0"" encoding=""gb2312""?〉")
currentpage=request("page")
if currentpage="" or int(currentpage)=0 then currentpage=1
set rs=server.createobject("adodb.recordset")
sql="select * from pl order by id desc"
rs.cursorlocation=3
rs.open sql,conn,1,1
if not rs.bof or not rs.eof then
rs.pagesize=5
rs.absolutepage=currentpage
rowcount=rs.pagesize
Response.write("〈pl tot='"&rs.recordcount&"' curpage='"¤tpage&"'〉")
do while not rs.eof and rowcount〉0
Response.write("〈pllist〉")
Response.write("〈user〉"&rs("user")&"〈/user〉")
Response.write("〈dateandtime〉"&rs("dateandtime")&"〈/dateandtime〉")
Response.write("〈content〉"&rs("content")&"〈/content〉")
Response.write("〈id〉"&rs("id")&"〈/id〉")
Response.write("〈/pllist〉")
rowcount=rowcount-1
rs.movenext
loop
else
Response.write("〈pl tot='"&rs.recordcount&"' curpage='"¤tpage&"'〉")
end if
rs.close
set rs=nothing
response.write("〈/pl〉")
%〉
Conn.asp 資料庫連結檔案,在刪除與提交處理中同樣使用
〈%
dim conn
dim connstr
dim db
db="main.mdb" '資料庫檔案位置
connstr="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & Server.MapPath(""&db&"")
set conn=server.createobject("ADODB.CONNECTION")
conn.open connstr
%〉
評論的刪除處理頁面:pl_list.asp
〈% Response.Charset="gb2312" %〉
〈% Session.CodePage=936 %〉
〈!--#include file="conn.asp"--〉
〈%
id=request("id")
if id="" then
response.write("參數錯誤!")
response.End()
end if
set rs=server.CreateObject("adodb.recordset")
sql="select * from pl where id="&id
rs.open sql,conn,1,3
rs.delete
rs.update
rs.close
set rs=nothing
response.write("刪除成功!")
%〉
評論的提交處理頁面:pl_fb.asp
〈% Response.Charset="gb2312" %〉
〈% Session.CodePage=936 %〉
〈!--#include file="conn.asp"--〉
〈%
user=request("user")
content=request("content")
newsid=request("newsid")
set rs=server.CreateObject("adodb.recordset")
sql="select * from pl"
rs.open sql,conn,1,3
rs.addnew
rs("user")=user
rs("content")=content
rs("newsid")=newsid
rs("dateandtime")=time()
rs.update
rs.close
set rs=nothing
response.write("添加成功!")
%〉
CSS樣式 main.css
一個好的頁面呈現效果離不開一個好的樣式,當然我這個屬於最基本的,算是看得清楚罷了,大家如果有興趣可以對樣式檔案作修改。
.u { /*呢稱*/
font-size: 12px;
float:left;
height:25px;
line-height:20px;
width:120px;
}
.d { /*時間*/
font-size: 12px;
float:left;
height:25px;
line-height:20px;
width:120px;
}
.idnub { /*刪除*/
text-align:center;
font-size: 12px;
height:25px;
line-height:25px;
width:30px;
}
.co {/*內容*/
font-size: 12px;
width:280px;
}
這是我第一次嘗試在asp中使用ajax,習慣於donet中的拖拖拉拉,突然用最原始的方式寫代碼還真有點不習慣,特別是缺少了那種所見即所得 (WYSIWYG)的效果,每一步的實現都得在不斷的調試中完成,的確是一件很累的事情。當然隨著Ajax式的程式開發愈來愈受歡迎,現在市面的架構、工具也越來越多,相信有那麼一天,開發Ajax應用程式終究會變成一件易常簡單的事。