讀古今文學網 > 編寫高質量代碼:改善JavaScript程序的188個建議 > 建議163:關注各種引擎對DOM解析的分歧 >

建議163:關注各種引擎對DOM解析的分歧

1.通過ID訪問HTML元素

對於IE來說,可以使用eval(\"idName\")或getElementById(\"idName\")獲取ID為idName的HTML元素,但非IE瀏覽器只能使用getElementById(\"idName\")來獲取ID為idName的HTML元素。通過ID訪問HTML元素一般直接使用document.getElementById就可以了。


<input type=\"button\"id=\"myButton\">

<script>

alert(document.getElementById(\"myButton\").value);

</script>


為了兼容低版本的IE,可以加上document.all。

提示:IE還支持把HTML元素的ID名作為document對象的屬性名直接使用,如document.idName。但其他引擎是不支持這種用法的,建議禁止使用。同時不要定義與HTML元素ID相同的變量名,以減少錯誤。在聲明變量時一律加上var關鍵字,以避免產生歧義。

2.集合類對像問題

在IE中可以使用或獲取集合類對象,而在非IE瀏覽器中只能使用獲取集合類對象,解決方法就是統一使用獲取集合類對象。

例如,訪問表單元素form,傳統方法支持使用document.form.item訪問表單對象,但IE允許document.formName.item(\"itemName\")或document.formName.elements[\"elementName\"]用法,Firefox等引擎僅支持document.formName.elements[\"elementName\"]用法。若想要兼容IE、Firefox等瀏覽器都能夠正常運行,那麼需要規範化訪問表單對象的方法,統一使用document.formName.elements[\"elementName\"]。


<body>

<form.name=\"myForm\">

<input id=\"txt\"/>

</form>

</body>

<script>

alert(document.myForm.elements[\"txt\"].value);

</script>


在Firefox中,在訪問數組時不能使用類似arr(\"itemName\")的形式,必須使用中括號,而在IE中兩者都可以。在使用時應該注意代碼的規範性,例如,下面兩種不同的寫法在Firefox等引擎中有不同的返回結果。

(1)錯誤寫法


<form.name=\"myForm\">

<input id=\"txt\"/>

</form>

<script>

alert(document.myForm);

alert(document.forms.length);//返回0,錯誤

</script>


(2)正確寫法


<body>

<form.name=\"myForm\">

<input id=\"txt\"/>

</form>

</body>

<script>

alert(document.myForm);

alert(document.forms.length);//返回1,正常

</script>


3.刪除節點

IE支持使用removeNode方法刪除節點。


<input type=\"button\"id=\"myButton\">

<script>

document.getElementById(\"myButton\").removeNode;

</script>


但Firefox等引擎沒有這個方法,只能先找到父節點,然後調用DOM的removeChild方法才可以刪除節點。不過IE也支持這種方法。


<input type=\"button\"id=\"myButton\">

<script>

var Node=document.getElementById(\"myButton\");

oNode.parentNode.removeChild(oNode);

</script>


4.交換節點

IE支持使用swapNode私有方法來交換兩個HTML元素節點。


<input type=\"button\"id=\"firstButton\">

<input type=\"button\"id=\"secondButton\">

<script>

var First=document.getElementById(\"firstButton\");

var Second=document.getElementById(\"secondButton\");

oFirst.swapNode(oSecond);

</script>


但Firefox不支持這種方法,要實現相同的操作,需要自定義函數。


<input type=\"button\"id=\"firstButton\">

<input type=\"button\"id=\"secondButton\">

<script>

if(window.Node){

Node.prototype.swapNode=function(node){

var nextSibling=this.nextSibling;

var parentNode=this.parentNode;

node.parentNode.replaceChild(this,node);

parentNode.insertBefore(node,nextSibling);

}

}

var First=document.getElementById(\"firstButton\");

var Second=document.getElementById(\"secondButton\");

oFirst.swapNode(oSecond);

</script>


5.插入節點

IE支持使用insertAdjacentHTML和insertAdjacentElement兩個私有方法來插入HTML節點。


<p></p>

<script>

var Div=document.getElementById(\"p1\");

var htmlInput=\"<input>\";

oDiv.insertAdjacentHTML(\'beforeEnd\',htmlInput);

</script>


但Firefox中沒有這兩個方法,為了兼容它們,可以統一使用DOM的insertBefore方法實現,IE也支持該方法。


<p></p>

<script>

var Div=document.getElementById(\"p1\");

var Element=document.createElement(\"input\");

oElement.type=\"text\";

oDiv.insertBefore(oElement,null);

</script>


6.訪問自定義屬性

對於IE來說,可以使用獲取常規屬性的方法來獲取自定義屬性,也可以使用getAttribute獲取自定義屬性。而非IE瀏覽器只能使用getAttribute獲取自定義屬性。解決方法是統一通過getAttribute獲取自定義屬性。

7.input.type屬性

在IE中,input.type屬性為只讀,但在其他瀏覽器中,input.type屬性為讀/寫。

8.window.location.href

IE支持使用window.location或window.location.href屬性,但其他引擎只能使用window.location。解決方法是使用window.location來代替window.location.href。

9.模態窗口和非模態窗口

IE可以通過showModalDialog和showModelessDialog來分別打開模態窗口和非模態窗口,其他引擎則不能。解決方法是直接使用window.open(pageURL,name,parameters)方式打開新窗口。要將子窗口中的參數傳遞回父窗口,可以在子窗口中使用window.opener來訪問父窗口。例如:


var parWin=window.opener;

parWin.document.getElementById(\"Aqing\").;


10.frame

以下面的frame為例。


<frame src=\"xxx.html\"id=\"frameId\"name=\"frameName\"/>


(1)訪問frame對像

IE使用window.frameId或window.frameName訪問這個frame對象,其他引擎只能使用window.frameName訪問這個frame對象。另外,所有引擎都可以使用window.document.getElementById(\"frameId\")來訪問這個frame對象。

(2)切換frame內容

所有引擎都可以使用如下代碼來切換frame內容。


window.document.getElementById(\"testFrame\").src=\"xxx.html\";



window.frameName.location=\"xxx.html\";


如果需要將frame中的參數傳回父窗口,可以在frme中使用parent來訪問父窗口,例如:


parent.document.form1.filename.;


如果在<frame>標籤中設置如下屬性:


<frame src=\"xx.htm\"id=\"frameId\"name=\"frameName\"/>


那麼IE可以通過id或name訪問該frame對應的window對象,其他引擎只能夠通過name來訪問該frame對應的window對象。

如果將上述<frame>標籤寫在頂層窗口的HTML中,那麼IE可以使用window.top.frameId或window.top.frameName訪問該window對象,其他引擎只能使用window.top.frameName訪問該window對象。不過,所有引擎都可以使用window.top.document.getElementById(\"frameId\")訪問<frame>標籤。

11.body

在IE中,當<body>標籤被瀏覽器完全讀入之後,body對像才存在,而其他引擎的body對象,在<body>標籤沒有被瀏覽器完全讀入之前就已存在。例如:

(1)非IE引擎


<body>

<script>

document.body.onclick=function(evt){

evt=evt||window.event;

alert(evt);

}

</script>

</body>


(2)兼容性用法


<body></body>

<script type=\"text/javascript\">

document.body.onclick=function(evt){

evt=evt||window.event;

alert(evt);

}

</script>


12.訪問父節點

對於父元素(parentElement),IE與其他引擎的訪問方法是不同的。

❑IE:obj.parentElement

❑Firefox:obj.parentNode

由於所有引擎都支持DOM,因此可以使用obj.parentNode兼容不同瀏覽器。

13.插入文本

IE支持使用innerText屬性為DOM元素插入文本,但其他引擎不支持這個屬性,卻支持textContent屬性。因此,解決方法如下:


if(navigator.appName.indexOf(\"Explorer\")>-1){

document.getElementById(\'element\').innerText=\"my text\";

}else{

document.getElementById(\'element\').textContent=\"my text\";

}


14.文本操作

不同瀏覽器對於<table>標籤的操作各不相同。IE不允許對table和tr對象的innerHTML賦值,也不支持使用appendChild方法添加tr對象。解決方法就是為table追加一個空行。


var row=otable.insertRow(-1);

var cell=document.createElement(\"td\");

cell.innerHTML=\"\";

cell.className=\"className\";

row.appendChild(cell);