常見的相容性問題

WindrunnerMax發表於2020-06-29

常見的相容性問題

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

初始化樣式

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

* { 
    margin: 0;
    padding: 0;
}

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

<link href="https://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="https://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="https://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="https://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
    <script type="text/javascript" src="https://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運算子
    () 子表示式運算子 用於與布林運算子建立更復雜的表示式
-->

每日一題

https://github.com/WindrunnerMax/EveryDay

參考

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