常見的兼容性問題

常見的兼容性問題

瀏覽器有著大量不同的版本,不同種類的瀏覽器的內核也不盡相同,所以不同瀏覽器對程式碼的解析會存在差異,這就導致對頁面渲染效果不統一的問題。

初始化樣式

因瀏覽器兼容的問題,不同的瀏覽器對標籤的默認樣式值不同,如果不初始化會造成不同瀏覽器之間的顯示差異,布局出現錯亂,所以要初始化樣式,達到統一的布局。
最粗暴的方案就是使用*初始化樣式,但是其會對於所有的標籤載入樣式以及計算樣式優先順序,可能會對性能有所影響。

* { 
    margin: 0;
    padding: 0;
}

通常使用Normalize.css抹平默認樣式差異,當然也可以根據樣式訂製自己的reset.css

<link href="//cdn.bootcss.com/normalize/7.0.0/normalize.min.css" rel="stylesheet">

內核樣式兼容

CSS3標準還未確定時,部分瀏覽器已經根據最初草案實現了部分功能,為了與之後確定下來的標準進行兼容,所以每種瀏覽器使用了自己的私有前綴與標準進行區分,當標準確立後,各大瀏覽器將逐步支援不帶前綴的CSS3新屬性,目前已有很多私有前綴可以不寫了,但為了兼容老版本的瀏覽器,可以仍沿用私有前綴和標準方法,逐漸過渡。

內核 代表瀏覽器 前綴
Trident IE瀏覽器 -ms
Gecko Firefox -moz
Presto Opera -o
Webkit Chrome、Safari -webkit

透明屬性

用來設定元素透明度的opacityCSS 3里的一個屬性,現代瀏覽器都已經支援,對於老版本瀏覽器可以通過加入私有前綴來支援,對於IE6-IE8可以通過filter屬性來支援,IE4-IE9都可以通過濾鏡寫法提供兼容支援。

opacity: 0.5;
-moz-opacity:0.5;
filter: alpha(opacity = 50); //IE6-IE8
filter: progid:DXImageTransform.Microsoft.Alpha(style = 0, opacity = 50); //IE4-IE9

媒體查詢

對於IE9以下瀏覽器不支援CSS3媒體查詢的問題,通常使用respond.js來作為兼容性解決方案。

<script type="text/javascript" src="//cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>

HTML5標籤

對於IE9以下瀏覽器不支援HTML5新標籤的問題,可以使用document.createElement創建元素並設置其CSS樣式即可,通常使用html5shiv.js來作為兼容性解決方案。

<script>
    document.createElement('header');
</script>
<style>
    header{display: block;}
</style>
<script type="text/javascript" src="//cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script>

placeholder兼容性

placeholderhtml5新增的一個屬性,當input或者textarea設置了該屬性後,該值的內容將作為灰字提示顯示在文本框中,當文本框獲得焦點或輸入內容時,提示文字消失。對於其兼容性首先需要判斷input是否支援placeholder,然後在不支援的情況下可以通過inputonfocusonblur事件監聽來實現placeholder效果。

<!-- 簡單示例 -->
<input type="text" value="Tips" onFocus="this.value = '';" onBlur="if (this.value == '') {this.value = 'Tips';}">

事件監聽句柄

IE9之前,必須使用attachEvent而不是使用標準方法addEventListener來註冊元素的監聽器,事件兼容的問題,通常需要會封裝一個適配器的方法,過濾事件句柄綁定、移除。

 var handler = {}

 //綁定事件
 handler.on = function(target, type, handler) {
 	if(target.addEventListener) {
 		target.addEventListener(type, handler, false);
 	} else {
 		target.attachEvent("on" + type,
 			function(event) {
 				return handler.call(target, event);
 		    }, false);
 	}
 };

 //取消事件監聽
 handler.remove = function(target, type, handler) {
 	if(target.removeEventListener) {
 		target.removeEventListener(type, handler);
 	} else {
 		target.detachEvent("on" + type,
 	    function(event) {
 			return handler.call(target, event);
 		}, true);
     }
 };

阻止默認行為

W3C推薦的阻止默認行為的方式是event.preventDefault(),此方法只會阻止默認行為而不會阻止事件的傳播。IE9之前的瀏覽器阻止默認行為需要使用window.event.returnValue = false。直接在事件處理函數中return false也能阻止默認行為,只在DOM0級模型中有效。此外,在jQuery中使用return false會同時阻止默認行為與事件傳播,通常也會封裝一個方法來實現默認行為的阻止。

handler.preventDefault = function(event) {
    event = event || window.event;
    if (event.preventDefault) {
        event.preventDefault();
    } else {
        event.returnValue = false;
    }
}

阻止事件冒泡

W3C推薦的阻止冒泡的方法是event.stopPropagation()IE9之前則是使用window.event.cancelBubble = true;,通常也會封裝一個方法來實現阻止事件冒泡。

handler.stopPropagation = function(event) {
    event = event || window.event;
    if (event.stopPropagation) {
        event.stopPropagation();
    } else {
        event.cancelBubble = false;
    }
}

滾動高度

獲取窗口的滾動高度scrollTop需要採用兼容性寫法,即使聲明<DOCTYPE>瀏覽器對於文檔的處理也會有所不同。

var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;

日期時間

使用new Date()構造函數生成日期時間對象,對於new Date("2020-06-29")語法在一些早期的瀏覽器會輸出invalid date,這主要是因為早期瀏覽器不支援表達日期的-,而/才是被廣泛支援的,所以在處理早期瀏覽器的兼容性時需要將-替換為/

new Date("2020-06-29".replace(/-/g, "/"));

IE條件注釋

IE專門提供的一種語法,只有IE能識別運行,其他瀏覽器只會作為註解。

<!--[if lt IE 9]>
    <script type="text/javascript" src="//cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
    <script type="text/javascript" src="//cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<![endif]-->
<!--[if !IE]>  除IE外都可識別   <![endif]-->
<!--[if IE]>   所有的IE可識別   <![endif]-->
<!--[if IE 6]>   僅IE6可識別   <![endif]-->
<!--[if lt IE 6]>   IE6以及IE6以下版本可識別   <![endif]-->
<!--[if gte IE 6]>   IE6以及IE6以上版本可識別   <![endif]-->
<!--[if IE 7]>   僅IE7可識別   <![endif]-->
<!--[if lt IE 7]>   IE7以及IE7以下版本可識別   <![endif]-->
<!--[if gte IE 7]>   IE7以及IE7以上版本可識別   <![endif]-->
<!--[if IE 8]>   僅IE8可識別   <![endif]-->
<!--[if IE 9]>   僅IE9可識別   <![endif]-->
<!-- 
    ! NOT運算符
    lt 小於運算符
    lte 小於或等於運算符
    gt 大於運算符
    gte 大於或等於運算符
    & AND運算符
    | OR運算符
    () 子表達式運算符 用於與布爾運算符創建更複雜的表達式
-->

每日一題

//github.com/WindrunnerMax/EveryDay

參考

//www.jianshu.com/p/c0b758a88c7c
//juejin.im/post/5b3da006e51d4518f140edb2
//juejin.im/post/59a3f2fe6fb9a0249471cbb4
Tags: