IE8瀏覽器的部分兼容性問題總結

1.    兼容性問題的根本因素

瀏覽器最重要或者說核心的部分是「Rendering Engine」,可大概譯爲渲染引擎,所謂的瀏覽器內核也就是瀏覽器所採用的渲染引擎,渲染引擎決定了瀏覽器如何顯示網頁的內容以及頁面的格式信息。不一樣的瀏覽器內核對網頁編寫語法的解釋也有不一樣,所以同一網頁在不一樣的內核的瀏覽器裏的渲染(顯示)效果也可能不一樣,這也是網頁編寫者須要在不一樣內核的瀏覽器中測試網頁顯示效果的緣由。javascript

前段時間進行了前端網頁的bug修改,發現多數的bug均發生在IE8瀏覽器上,通過查證發現:IE8JavaScript引擎是JscriptIE9開始用Chakra,這兩個版本區別很大,這就形成了IE8對於個別屬性、方法的不支持或是顯示效果上的差別,這裏是我遇到的一些IE8上比較典型的兼容性問題及其解決辦法。html

2.    indexOf

1       前端

2       java

2.1      問題

前端代碼中有多處地方使用javascript數組的indexOf方法,用於查詢某數組中是否存在某元素,然而測試,在IE8不支持數組元素的indexOf()方法。以下web

              var location = ['1','2','3'];ajax

              var serverData = [‘1’ , ’4’, ‘5’];chrome

              for( var i = 0; i < serverData.length; i++ )編程

              {數組

                     if( location.indexOf( serverData[i].location ) == -1 )瀏覽器

                            location.push( serverData[i]);

                     }

}

上述js代碼的功能是將數組serverData出現的新元素添加如location中。該方法在火狐、chrome瀏覽器中支持,但在IE8中並不支持。

2.2      解決辦法

方法一:

數組元素轉化爲字符串後,再使用indexOf()方法。

              var location = ['1','2','3'];

              var serverData = [‘1’ , ’4’, ‘5’];

              for( var i = 0; i < serverData.length; i++ )

              {

                     if( location.join().indexOf( serverData[i].location ) == -1 )

                            location.push( serverData[i]);

                     }

方法二(推薦方法):

添加以下js代碼:

    if (!Array.prototype.indexOf)

    {

      Array.prototype.indexOf = function(elt /*, from*/)

      {

        var len = this.length >>> 0;

 

        var from = Number(arguments[1]) || 0;

        from = (from < 0)

             ? Math.ceil(from)

             : Math.floor(from);

        if (from < 0)

          from += len;

 

        for (; from < len; from++)

        {

          if (from in this &&

              this[from] === elt)

            return from;

        }

        return -1;

      };

    }

當瀏覽器對於數組不支持indexOf()方法時,就爲數組添加該方法。

該方法會在瀏覽器不支持數組的indexOf方法時,爲其手動添加indexOf方法,實現瀏覽器的兼容。

3.    ajax請求響應的異常狀態碼1223

3       

3.1      問題

1-    AJAX狀態值與狀態碼區別

AJAX狀態值是指,運行AJAX所經歷過的幾種狀態,不管訪問是否成功都將響應的步驟,能夠理解成爲AJAX運行步驟。如:正在發送,正在響應等,由AJAX對象與服務器交互時所得;使用「ajax.readyState」得到。(由數字1~4單位數字組成)

AJAX狀態碼是指,不管AJAX訪問是否成功,由HTTP協議根據所提交的信息,服務器所返回的HTTP頭信息代碼,該信息使用「ajax.status」所得到。以下判斷:

if(ajax.readyState == 4 && ajax.status ajax.status == 200)

最近在處理前端與服務器的交互時,發如今IE下發出的ajax請求,有時會會返回錯誤的狀態碼 1223。咱們經常使用的狀態碼列表中並無該狀態碼。

3.2      解決辦法

通過查證發現,在斷定一個請求是否已經完成的時候,驗證xhrstatus有一點是須要注意的:有的瀏覽器會錯誤地返回204狀態碼,而IE(非原生的XHR對象)中會將204設置爲1223Opera會在取得204時將status設置爲0,而Safari 3以前的版本會將status設置爲undefined

咱們經常使用的狀態碼:

200——請求成功

204——請求收到,但返回信息爲空

即在IE瀏覽器下,狀態碼1223204是等價的,一樣爲請求收到,但返回信息爲空,咱們只須要將ajax.status==1223的判斷加入ajax.status==204的判斷中便可。

4.    文件下載

4       

4.1      IE瀏覽器的文件下載

4.1.1          方法

       在前端的修改中,我遇到了兩種下載文件的方式,一種是將服務器的文件下載到本地,另外一種是在本地將數據保存爲對應格式的文件下載下來。如今推薦的是第一種方法。

              var aLink = document.createElement("a"),

              evt = document.createEvent("HTMLEvents"),

              isData = contentOrPath.slice(0, 5) === "data:",

              isPath = contentOrPath.lastIndexOf(".") > -1;

       // 初始化點擊事件

       evt.initEvent("click",false,false);

       // 添加文件下載名

       aLink.download = fileName;

       // 若是是 path 或者 dataURL 直接賦值

       // 若是是 file 或者其餘內容,使用 Blob 轉換

       aLink.href = (isPath || isData) ? contentOrPath

                                   : URL.createObjectURL(new Blob([contentOrPath]));

       aLink.dispatchEvent(evt);

       利用a標籤能夠實現下載文件的效果

<a href="/images/myw3schoolimage.jpg" download="w3logo">

    經過爲其添加download屬性,可使其完成文件下載的功能。

4.1.2          侷限

只有 Firefox Chrome 支持 download 屬性。

IE下的文件下載能夠經過document.execCommand()完成。

這裏使用了事件模擬來觸發標籤a的下載事件。

4.1.3          IE瀏覽器的模擬事件

模擬事件大體分爲模擬鼠標事件、模擬鍵盤事件、模擬變更事件及模擬HTML事件等。

模擬事件的過程大體分爲三步:

1.  建立event對象。

經過createEvent()能夠建立event對象,而傳入字符串的不一樣能夠決定,如var event = document.createEvent(「MouseEvents」);  //建立鼠標事件對象

event = document.createEvent(「KeyboardEvent」); //建立鍵盤事件對象

2.  初始化事件對象

不一樣類型的模擬事件對象有着不一樣的初始化參數

event.initMouseEvent(「click」, true, true, document.defaultView, 0, 0, 0, 0, 0,false, false, false, false, 0, null);// 鼠標事件對象初始化

iniMouseEvent()方法接受15參數,參數以下:
  type string類型 :要觸發的事件類型,例如‘click’
  bubbles Boolean類型:表示事件是否應該冒泡,針對鼠標事件模擬,該值應該被設置爲true
  cancelable bool類型:表示該事件是否可以被取消,針對鼠標事件模擬,該值應該被設置爲true
  view 抽象視圖:事件授予的視圖,這個值幾乎全是document.defaultView.
  detail int類型:附加的事件信息這個初始化時通常應該默認爲0
  screenX int類型 事件距離屏幕左邊的X座標
  screenY int類型 事件距離屏幕上邊的y座標
  clientX int類型 事件距離可視區域左邊的X座標
  clientY int類型 事件距離可視區域上邊的y座標
  ctrlKey Boolean類型 表明ctrol鍵是否被按下,默認爲false
  altKey Boolean類型 表明alt鍵是否被按下,默認爲false
  shiftKey Boolean類型 表明shif鍵是否被按下,默認爲false
  metaKey Boolean類型: 表明meta key 是否被按下,默認是false
  button int類型: 表示被按下的鼠標鍵,默認是零.
  relatedTarget (object) 事件的關聯對象.只有在模擬mouseover mouseout時用到。

 

 event.initKeyboardEvent(「keydown」, true, true, document.defaultView, 「a」,0, 「Shift」, 0); //鍵盤事件對象初始化。

初始化鍵盤事件的參數有如下幾個:

type (string) - 要觸發的事件類型,例如「keydown」.
  bubbles (Boolean) — 表明事件是否應該冒泡.
  cancelable (Boolean) — 表明事件是否能夠被取消.
  view (AbstractView) — 被授予事件的是圖. 一般值爲:document.defaultView.
  key (string) — 按下的鍵對應的code.
  location (integer) — 按下鍵所在的位置. 0 :默認鍵盤, 1 左側位置, 2 右側位置, 3 數字鍵盤區, 4 虛擬鍵盤區, or 5 遊戲手柄.
  modifiers (string) — 一個有空格分開的修飾符列表.
  repeat (integer) — 一行中某個鍵被按下的次數.

3.  觸發模擬事件

經過dispatchEvent(event)來實現。

4.2      IE下的文件下載

4.2.1          方法

       IE下的文件下載能夠經過document.execCommand()完成。

4.2.2          execCommand()

document.execCommand()方法處理Html數據時經常使用語法格式以下:
document.execCommand(sCommand[,交互方式, 動態參數])

中:sCommand爲指令參數(以下例中的」2D-Position」),交互方式參數若是是true的話將顯示對話框,若是爲false的話,則不顯 示對話框(下例中的」false」即表示不顯示對話框),動態參數通常爲一可用值或屬性值(以下例中的」true」)。

document.execCommand(」2D-Position」,」false」,」true」);

調用execCommand()能夠實現瀏覽器菜單的不少功能. 如保存文件,打開新文件,撤消、重作操做等等. 有了這個方法,就能夠很容易的實現網頁中的文本編輯器.

若是靈活運用,能夠很好的輔助咱們完成各類項目.

使用的例子以下:

1、〖全選〗命令的實現
[格式]:document.execCommand(」selectAll」)
[說明]將選種網頁中的所有內容!
[舉例]在之間加入:
全選

2、〖打開〗命令的實現
[格式]:document.execCommand(」open」)
[說明]這跟VB等編程設計中的webbrowser控件中的命令有些類似,你們也可依此琢磨琢磨。
[舉例]在之間加入:
打開

3、〖另存爲〗命令的實現
[格式]:document.execCommand(」saveAs」)
[說明]將該網頁保存到本地盤的其它目錄!
[舉例]在之間加入:
另存爲

4、〖打印〗命令的實現
[格式]:document.execCommand(」print」)
[說明]固然,你必須裝了打印機!
[舉例]在之間加入:
打印

 

execCommand()還有許多其餘方面的功能,詳細的介紹參考:

http://blog.csdn.net/kntao/article/details/4543123

 

4.2.3          IE中的事件模擬

IE8,以及更早版本的IE,都在模仿DOM模擬事件的方式:建立事件對象,初始化事件信息,以後觸發事件。固然IE在完成這幾個步驟的過程是不一樣的。

首先不一樣於dom中建立event對象的方法,IE採用document.createEventObject()方法,而且沒有參數,返回一個通用的事 件對象,接下來要對返回的event對象賦值,此時ie並無提供初始化函數,你只能採用物理方法一個一個的賦值,最後在目標元素上調用 fireEvent()方法,參數爲兩個:事件處理的名稱和建立的事件對象。當fireEvent方法被調用的時候,event對象的 srcElementtype屬性將會被自動賦值,其餘將須要手動賦值。

示例以下:

var btn = document.getElementById("myBtn");
  var event = document.createEventObject();
  event.screenX = 100;
  event.screenY = 0;
  event.clientX = 0;
  event.clientY = 0;
  event.ctrlKey = false;
  event.altKey = false;
  event.shiftKey = false;
  event.button = 0;
  btn.fireEvent("onclick", event);

       這裏只是簡單的介紹了一些經常使用的模擬事件,詳細的解釋能夠參考

Javascript高級程序設計》,裏面有更加詳細的介紹。

5.    IE下單選按鈕隱藏後點擊對應label沒法選中的問題解決

5       

5.1      問題

項目中,有時候填寫表單咱們的選項會隱藏掉radio或者checkbox,而只顯示給用戶對應的文字選擇,若是用戶點擊label選擇時,在FF/Chrome等標準瀏覽器中隱藏掉的radio/checkbox也一樣隨着改變選中狀態,而在IE下則不會發生變化。

注意,須要指定表單元素的id屬性而後使用labelfor屬性綁定控件。

代碼示例:
<input type="radio" name="gender" id="gender1" value="" checked="checked" />
<label for="gender1"></label>
<input type="radio" name="gender" id="gender2" value="" />
<label for="gender2"></label>
經過CSS設置display:none 或者 visibility: hidden隱藏掉radio按鈕,則當點擊label切換選擇狀態時,對應的按鈕其實是未被改變狀態。

5.2      解決方法

方法一:

1.經過javascript腳原本再次操做DOM保證選擇狀態
$("label").click(function(e){
    e.preventDefault(); 
    $("#"+$(this).attr("for")).click().change(); 
});

方法二(推薦):

不使用display:none,經過position屬性定位到可視區域外,避開問題。
position: absolute;
top: -999px;

方法三:

left: -999px;經過z-index/width或透明度opacity將元素隱藏掉。
input{
    position: absolute;
    z-index: -1;
}
或者是
input{
width: 0;
}
或者是
input{
-webkit-opacity:0;
-moz-opacity:0;
opacity:0;
filter:alpha(opacity:0);

}

須要提醒的是,labelfor屬性是內聯元素,其對應的js屬性爲htmlFor,例如能夠這樣訪問或設置for屬性值。document.getElementById("xxx").htmlFor="inputid";

6.    總結

低版本IE瀏覽器對於對於網頁內容及格式的渲染有着這樣或那樣的問題,然而爲了實現向下的兼容,這些問題又是不可忽略的,無論怎樣,可以提早了解這些差別,總會給咱們前端的實現帶來一些,避免一些沒必要要的問題。

相關文章
相關標籤/搜索