問題提出
最近計劃重構網普科技的網站,小試牛刀一下,用PHP+XAjax實現了一個功能簡單的小頁面(http://www.netpu.net/test/test.php)。不曾想這個頁面在Firfox中測試一直很正常,到IE7下測試則時而正常,時而出錯。開啟XAjax的Debug功能,也沒能擷取有價值的資訊,非常鬱悶。
於是使用Ajax+IE7作為關鍵字,到搜尋引擎中去搜尋,找到很多關於Ajax代碼在IE7下運行出錯的文章,但都是有人發問無人回答,看來只好自己去解決啦。
解決思路
既然這個頁面在Firefox和IE6上都運行正常,那麼我們來看看Firefox與IE6、IE7在處理Ajax代碼時都有哪些區別吧?
我們知道,Ajax 應用程式的核心是XMLHttpRequest,但是由於不同瀏覽器的相容問題,建立這個對象的方法是有很大的區別的。
在Mozilla、Firefox、Safari、Opera等瀏覽器上,使用下邊的語句建立XMLHttpRequest:
CODE: [Copy to clipboard]
var xmlHttp = new XMLHttpRequest();
而在IE6及以下版本,則使用以下語句建立XMLHttpRequest:
CODE: [Copy to clipboard]
xmlHttp = new ActiveXObject("Msxml2.XMLHTTP"); 或
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
那IE7又與IE6有些什麼區別呢?
在MSDN上:About Native XMLHTTP一文中裡邊有這樣的說明:
http://msdn2.microsoft.com/en-us/library/ms537505.aspx
In Internet Explorer 6 and earlier, XMLHTTP was implemented as an ActiveX object provided by Microsoft XML (MSXML). Beginning with Internet Explorer 7, XMLHTTP is also exposed as a native scripting object.
也就是說IE7增加了Native XMLHTTP支援。
同時裡邊給了一段範例程式碼:
CODE: [Copy to clipboard]
var xmlHttp = null;
if (window.XMLHttpRequest) {
// If IE7, Mozilla, Safari, and so on: Use native object.
xmlHttp = new XMLHttpRequest();
}
else
{
if (window.ActiveXObject) {
// ...otherwise, use the ActiveX control for IE5.x and IE6.
xmlHttp = new ActiveXObject('MSXML2.XMLHTTP.3.0');
}
}
由此可以看出,IE7比IE6多了Native XMLHTTP支援。那麼會不會是這個Native XMLHTTP導致的問題呢?不用這個Native XMLHTTP會怎麼樣?還好IE7的設計者也考慮了這一點,IE7提供了兩個功能:
一個是通過設定來禁用“Native XMLHTTP支援”(預設是開啟)。
挑掉Enable Native XMLHTTP support上的勾就可以禁用它了。
另外一個功能就是相容IE6建立XMLHttpRequest的方法。
解決方案
OK,既然這樣,我們禁用“Native XMLHTTP支援”,看看我們的程式是否正常了?
測試結果,我們的程式一切正常。
但是等等,我們總不能要求使用者訪問我們的頁面之前禁用“Native XMLHTTP支援”吧?汗一下!
於是我們只能在Ajax的XMLHttpRequest建立代碼上想辦法了。
想什麼辦法呢?說實話,對Ajax我是超級外行,沒辦法,硬著頭皮來吧。既然問題出在建立XMLHttpRequest對象上,那麼我們就從這裡下手吧。
網上很多文章都強調,為了跨瀏覽器安全色,首先檢查是否支援Native XMLHTTP。
比如這篇文章:Ajax on IE 7: Check native first
http://ajaxian.com/archives/ajax-on-ie-7-check-native-first
還有前文提到的IE7建立XMLHttpRequest的範例程式碼,也是先檢查是否支援Native XMLHTTP的。看看我們用的XAjax是咋建立對象的吧。
CODE: [Copy to clipboard]
/*
Function: getRequestObject
Construct an XMLHttpRequest object dependent on the capabilities
of the browser.
Returns:
object - Javascript XHR object.
*/
if ("undefined" != typeof XMLHttpRequest) {
xajax.tools.getRequestObject = function() {
return new XMLHttpRequest();
}
} else if ("undefined" != typeof ActiveXObject) {
xajax.tools.getRequestObject = function() {
try {
return new ActiveXObject("Msxml2.XMLHTTP.4.0");
} catch (e) {
xajax.tools.getRequestObject = function() {
try {
return new ActiveXObject("Msxml2.XMLHTTP");
} catch (e2) {
xajax.tools.getRequestObject = function() {
return new ActiveXObject("Microsoft.XMLHTTP");
}
return xajax.tools.getRequestObject();
}
}
return xajax.tools.getRequestObject();
}
}
} else if (window.createRequest) {
xajax.tools.getRequestObject = function() {
return window.createRequest();
}
} else {
xajax.tools.getRequestObject = function() {
throw { name: 'GetRequestObject', message: 'XMLHttpRequest is not available, xajax is disabled' }
}
}
果然不出我們預料,也是先檢查是否支援Native XMLHTTP的。這樣一來一旦使用的是IE7,那麼IE7的Native XMLHTTP會被啟用,我們的程式就會出錯啦。
換個策略,我們如果先檢查ActiveX object對象呢?說做就做,我們修改了這部分代碼(簡單地說就是調換了一下順序),測試,一切正常,Firefox、IE6、IE7都正常(抱歉我手頭只有這幾個瀏覽器。
至此大功告成!您問我修改後的代碼呢?這個留給大家做個小練習吧,超級簡單哦。或者您可以到網普技術論壇(http://bbs.netpu.net)來尋求協助。