主题:【原创】AJAX在西西河的一个应用简析 -- 铁手
Asynchronous JavaScript and XML ==> AJAX
关于AJAX的历史和一些应用以及实现机理,可以在GOOGLE里很容易的查找到,这里就不多说。只是简单的说明一下它目前在西西河的第一个应用,以及在使用过程中所碰到的问题,并请熟悉的朋友讨论指点一下。
AJAX的机理,说起来很简单,就是在 JAVACRIPT 中直接和服务器取得联系,把相关内容拿回到客户端,然后把零件一个个拆下来,再分别放到当前页面中合适的地方去。
最核心的部分,就是在JAVASCRIPT中实现静悄悄获取页面内容的的功能模块。
这个功能,在非IE的浏览器中很容易实现,因为这些浏览器里都内置这个模块。用以下的语句,可以得到这个功能模块。
if (window.XMLHttpRequest) {
zHTTP_Req = new XMLHttpRequest();
if (zHTTP_Req.overrideMimeType) {
zHTTP_Req.overrideMimeType("text/xml");
}
}
如果是IE浏览器,则需要ActiveXObject的支持,可以用以下语句得到
if (window.ActiveXObject){
try{
zHTTP_Req = new ActiveXObject("Microsoft.XMLHTTP");
}catch(e){
try{
zHTTP_Req = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {}
}
}
在得到这个打开后门偷偷交流的功能模块后(在这里是 zHTTP_Req),需要做的事情就是告诉这个模块在什么情况下做什么事情。这个是通过事件驱动来实现,具体的说,就是给这个模块的 onreadystatechange 事件定义一个函数。
function IfYouClickMeIWillKickYouBack{ // 用来对某个BUTTON点击做反应的函数
zHTTP_Req.onreadystatechange = function(){
if (zHTTP_Req.readyState == 4) {
if (zHTTP_Req.status == 200) {
var zlTmpV = zHTTP_Req.responseXML.getElementsByTagName("UPInfo")[0].childNodes[0].nodeValue; //XML的格式
。。。
。。
//zlDobj.innerHTML = zHTTP_Req.responseText; //文本方式得到内容
}
}
}
zHTTP_Req.open("GET", url, true); //我要看到某个页面的内容。
zHTTP_Req.send(null);
}
上面这段里,在提出要得到某个页面的内容的请求后,这个功能模块不断检测请求是否得到响应,内容是否正常返回。
正常返回后,可以有两种方式来得到所请求的内容。如果是简单的文本,可以用 zHTTP_Req.responseText ,如果是XML格式的,则需要相应的处理,来得到分类的内容。
西西河目前的一个简单AJAX应用,是实现在论坛首页最下面的【发贴信息】这个链接里。FIREFOX,SAFARI里面都没有任何问题,但是在IE里面,有时候可以有时候不可以,邪门的很。
还有一个问题,我原本是想用简单的文本方式,也就是在所请求的URL里,把内容都格式好以后(包括HTML 标签符号)输出,希望能够使用 responseText 来直接放到页面某个位置,结果所有中文都成为????的形式,而英文、数字等则没有显示问题。
后来不得以,只能使用 responseXML 来实现。只是,对XML也不是很熟悉。河里的XML FEED,也是用了尽可能简单的方式。
如果有人能够解决 responseText 中文内容乱码的问题的话,事情就会简单很多,西西河里很多地方也可以应用一下。
比如这一个
微软对AJAX的支持将是全方位的,从Server到Client端。现在他们搞了一个Project,叫做Atlas,就是要全面进军AJAX,并且要让Programmer近量不手写JavaScript。
另外,最近看到FLASH里面也有类似的功能,这么一想,缺点大家一样,都是对搜索引擎不友好,甚至AJAX还要冒用户关闭JAVASCRIT的风险,好处上面,FLASH的画面显然要好一些,还真不知道以后到底是谁的天下:)
输出这个片段response的时候,有没有设charset=gb2132?
不过,也许可以尝试一下使用一下输出一个完整页面,包括字符集信息,然后在JAVASCRIPT中再做分离提取。
不过,如果那么做的话,似乎和用XML就没有多少区别了。
老兄有没有试试写response的时候直接设HTTP header里的ContentType? 手边没有.NET的API文档,大概是:
response.CharSet="GB2312";
AJAX没做过,不知道啊。不过servlet在response输出日语的时候是需要指定编码shift-jis的,我估计这个也需要指定一下。毕竟这些东西都是西方人搞得,默认的方式应该不支持双字节。
我用的是PHP。又试了一下。我用一个HTML的静态文件为源,也同样是乱码。不过如果这个文件是UTF-8的格式保存的话,则可以正常显示。
看来这个源需要是UTF-8的编码方式。
看来有必要不管死活也要转到UNICODE上了????GB18030怎么办?
我弄过一点AJAX,希望能帮个小忙。
乱猜一下原因,有几个地方都会用到ENCODING。
硬盘上的文件有它自己的ENCODING,比如在XP上,用NOTEPAD,你可以把一个文件用ANSI,UTF-8,UNICODE等方式存取,如果打开的ENCODING与存放的ENCODING不一致,会有乱码。
另外,服务器与客户端的转输内容,也会。对于XML,UTF-8是DEFAULT的,如果你的文件ENCODING不是UTF-8,应当转成UTF-8。否则也会有乱码。如用HTML,可以检查一下DEFAULT ENCODING,如果不一致,你有可能也需要转一下码。
当然,还有一个地方就是客户端的BROWSER,不过不太可能。
如果原文件是UTF-8的,直接用TEXT没有问题。
不过那样的话,我想可能还是直接用XML格式比较好一些,因为在XML里可以设定语言,也不占太多空间。
用XML的问题是如果要用格式化的HTML段落,需要用对格式码编码,会增加一些流量。呵呵,这方面我很小心,传送数据越少越好。
我现在有两个问题:
一个是XML的元素怎么在用JAVASCRIPT获取。我用的比较简单,就是
zHTTP_Req.responseXML.getElementsByTagName("UPInfo")[0].childNodes[0].nodeValue;
这样的方式,但是如果是有多个NODE呢?这方面暂时没时间去学。如果你能够另开一个主题专门谈这个的话,实在是很感谢了。
还有一个问题,就是我现在这个应用中,在IE里老是出现OBJECT NOT FOUND的错。出错点就在上面列举的那段获得NODE值的代码里,不知道错在什么地方。
不过那样的话,我想可能还是直接用XML格式比较好一些,因为在XML里可以设定语言,也不占太多空间。
事实上,XML文件内容的ENCODING和XML文件里设置可以是不一样的。比如,你可以把在XML PROLOG里将ENCODING设成是ISO-8859-1,但是如果将这个文件本身用UTF-8方式存到硬盘上,就会造成不一致,可能会出现乱码,当然如果文件本身存成UTF-8格式,就没有问题了。
另外在上一帖里,我忘了谈WEB SERVER或其PLUGIN本身ENCODING问题,因为我用的是J2EE平台,而JAVA内部的ENCODING总是UNICODE。JAVA在读外部文件时,如果不指定特别的ENCODING参数,总是用所在的计算机DEFAULT ENCODING,然后将其转为UNICODE的,写的时候反过来,会将UNICODE转成所在的计算机DEFAULT ENCODING。
一个是XML的元素怎么在用JAVASCRIPT获取。我用的比较简单,就是
zHTTP_Req.responseXML.getElementsByTagName("UPInfo")[0].childNodes[0].nodeValue;
这样的方式,但是如果是有多个NODE呢?这方面暂时没时间去学。如果你能够另开一个主题专门谈这个的话,实在是很感谢了。
另开主题,我都不知道该说些什么,又从何而谈。针对你的问题说两句,如果你的XML比较复杂,建议直接用HTML;如果你的XML比较简单,比如,在ROOT下只有一个层,如这个例子
<myxmlroot>
<xyz> ... </xyz>
<123>... </123>
....
</myxmlroot>
[/QUTOE]
也就是说,XYZ和123这样的NODE里再不包含SUBNODE,就可以这样干
[QUOTE]var root, i, oNodeList, item;
root = xmlDoc.documentElement;
oNodeList = root.childNodes;
for (i=0; i<oNodeList.length; i++)
{
Item = oNodeList.item(i);
// ....
}
如果你可以给我URL,我可以给你写一个简单的框架。如果是HTML的,我可以帮你试
一下错误在什么地方。
用AJAX来GET回一个页面时,RESPONSETEXT里面的中文多半会出现乱码,这是因为xmlhttp在处理返回的responseText的时候,是把resposeBody按UTF-8编码进解码考形成的,如果服务器送出的确实是UTF-8的数据流的时候汉字会正确显示,而送出了GBK编码流的时候就乱了。解决的办法就是在送出的流里面加一个HEADER,指明送出的是什么编码流,这样XMLHTTP就不会乱搞了。
PHP:header('Content-Type:text/html;charset=GB2312');
ASP:Response.Charset("GB2312")
JSP:response.setHeader("Charset","GB2312");
XMLHTTP得到Response时假定Response是UTF8编码的,如果Response是 XML,那还可以通过encoding来指定编码,但HTML就不行了。(见鬼的GB2312,再次打倒!)所以它把含GB2312编码的HTML当成 UTF8格式,不出错才有鬼!
不过好在还有补救的办法:XMLHTTP的responseBody 属性里包含的可是未解码的Resonse——"a raw undecoded bytes as received directly from the server" :),唯一的问题是,responseBody返回的是一个unsigned bytes数组,我们怎么去访问它,怎么把它转换成BSTR?
这就是为什么我在上面把代码改成VBScript的原因——VBScript Can do it,but javascript Cannot!
代码见下:
<SCRIPT language="VBScript">
Function URLEncoding(vstrIn)
strReturn = ""
For i = 1 To Len(vstrIn)
ThisChr = Mid(vStrIn,i,1)
If Abs(Asc(ThisChr)) < &HFF Then
strReturn = strReturn & ThisChr
Else
innerCode = Asc(ThisChr)
If innerCode < 0 Then
innerCode = innerCode + &H10000
End If
Hight8 = (innerCode And &HFF00)\ &HFF
Low8 = innerCode And &HFF
strReturn = strReturn & "%" & Hex(Hight8) & "%" & Hex(Low8)
End If
Next
URLEncoding = strReturn
End Function
Function bytes2BSTR(vIn)
strReturn = ""
For i = 1 To LenB(vIn)
ThisCharCode = AscB(MidB(vIn,i,1))
If ThisCharCode < &H80 Then
strReturn = strReturn & Chr(ThisCharCode)
Else
NextCharCode = AscB(MidB(vIn,i+1,1))
strReturn = strReturn & Chr(CLng(ThisCharCode) * &H100 + CInt(NextCharCode))
i = i + 1
End If
Next
bytes2BSTR = strReturn
End Function
strA = URLEncoding("submit1=Submit&text1=中文")
oReq = CreateObject("MSXML2.XMLHTTP")
oReq.open "POST","http://ServerName/VDir/TstResult.asp",false
oReq.setRequestHeader "Content-Length",Len(strA)
oReq.setRequestHeader "CONTENT-TYPE","application/x-www-form-urlencoded"
oReq.send strA
alert bytes2BSTR(oReq.responseBody)
</ScRIPT>
用这个再试试看?