浏览器兼容性问题

# 浏览器兼容性问题

[TOC]

IE8/9/10/11Edge、Chrome、Firefox

兼容性查询:https://caniuse.com/ (opens new window)

判断浏览器:https://github.com/mumuy/browser/blob/master/Browser.js(浏览器检测 亲测有效)

# 一、CSS样式

# 1.1 浏览器样式差异

# 1.1.1 reset.css

重置样式,抛弃默认样式。

# 1.1.2 normalize.css

让浏览器的标签都跟标准规定的默认样式一致,各浏览器上的标签默认样式基本统一。

# 1.2 浏览器兼容前缀

在CSS3还没有成为真正的标准时,浏览器厂商就开始支持这些属性的使用了。CSS3样式语法还存在波动时,浏览器厂商提供了针对浏览器的前缀,直到现在还是有部分的属性需要加上浏览器前缀。在开发过程中我们一般通过IDE开发插件、css 预处理器以及前端自动化构建工程帮我们处理。

vue-cli会自动补充前缀。

内核 主浏览器 前缀
Trident三叉戟 /'traidnt/ IE -ms-
EdgeHTML Edge
Gecko壁虎 /'gɛko/ Firefox -moz-
Presto很快 /'prestou/ Opera -o-
Blink(28~)/ Webkit(Chrome 27) Chrome -webkit-
Webkit装备 Safari -webkit-

# 1.2.1 动画

  • transform
transform:rotate(4deg);			//统一标识语句
-webkit-transform:rotate(4deg);	//Chrome、Safari
-moz--transform:rotate(4deg);	//Firefox
-o-transform:rotate(4deg);		//Opera
-ms-transform:rotate(4deg);		//IE
1
2
3
4
5
  • @keyframes
  • transition
  • animation

# 1.2.2 透明度

opacity: 0.5;
filter: alpha(opacity = 50);	// 兼容IE8
1
2

# 1.2.3 渐变

  • linear-gradient
  • radial-gradient

# 1.2.4 边框

  • border-radius:需兼容IE8、Opera
  • box-shadow:需兼容IE8、Opera

# 1.3 兼容模式

<!--什么版本IE就用什么版本的标准模式:-->
<meta http-equiv="X-UA-Compatible" content="IE=edge">

<!--使用以下代码强制IE使用Chrome Frame:-->
<meta http-equiv="X-UA-Compatible" content="chrome=1">

<!--最佳的兼容模式方案,结合考虑以上两种:-->
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
1
2
3
4
5
6
7
8

# 二、JS兼容

# 2.1 事件

方法 标准 IE
监听事件 element.addEventListener() 有捕获无on element.attachEvent() 无捕获有on
事件对象 event window.event
目标元素 event.target event.srcElement
取消默认事件 event.preventDefault() IE8以上 event.returnValue = false
解绑事件 element.removeEventListener() element.detachEvent()
阻止冒泡 event.stopPropagation() event.cancelBubble = true IE11以下
  • 取消默认事件
//无兼容问题(但不能用于节点直接onclick绑定函数)
return false;
1
2
  • EventUtil
var EventUtil = {

    addHandler: function (element, type, handler) {
        if (element.addEventListener) {
            element.addEventListener(type, handler, false);
        } else if (element.attachEvent) {
            element.attachEvent("on" + type, handler);
        }
    },

    getEvent: function (event) {
        return event || window.event;
    },

    getTarget: function (event) {
        return event.target || event.srcElement;
    },

    preventDefault: function (event) {
        if (event.preventDefault) {
            event.preventDefault();
        } else {
            event.returnValue = false;
        }
    },

    removeHandler: function (element, type, handler) {
        if (element.removeEventListener) {
            element.removeEventListener(type, handler, false);
        } else if (element.detachEvent) {
            element.detachEvent("on" + type, handler);
        }
    },

    stopPropagation: function (event) {
        if (event.stopPropagation) {
            event.stopPropagation();
        } else {
            event.cancelBubble = true;
        }
    }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
btn.onclick = (event) => {
    // 这一步要先写
    let event = EventUtil.getEvent(event);
    let target = EventUtil.getTarget(event);
};
1
2
3
4
5

# 2.2 浏览器窗口

# 2.2.1 滚动条滚动距离

//标准浏览器
document.documentElement.scrollTop[scrollLef]
//谷歌浏览器
document.body.scrollTop[scrollLeft]
//兼容不同的浏览器
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop
1
2
3
4
5
6

# 2.2.2 窗口大小

document.documentElement.clientWidth || document.body.clientHeight
1

# 2.3 样式

# 2.3.1 浮动

// IE
oDiv.style.styleFloat = 'left';
// 非IE
oDiv.style.cssFloat = 'left';
// 兼容模式
oDiv.style.cssText = 'float: left;';
1
2
3
4
5
6

# 2.3.2 获取样式

// 兼容IE8,IE独有
if(obj.currentStyle) {
    return obj.currentStyle[attr];
} else {
    // 兼容火狐谷歌,IE9以上
    // 不能通过document对象调用,只能通过一个元素节点对象调用它
    return getComputedStyle(obj)[attr];
}
1
2
3
4
5
6
7
8

# 2.4 滚动事件

兼容所有HTML5浏览器:

window.onwheel = (e) => {
        console.log(e.deltaY);
}

// 上:-100;下:100
1
2
3
4
5

# 2.4.1 onmousewheel/DOMMouseScroll

ie/chrome : onmousewheel firefox : DOMMouseScroll 必须用addEventListener

oDiv.onmousewheel = fn;
//因为ie没有addEventListener这个属性,所以要做判断
oDiv.addEventListener && oDiv.addEventListener('DOMMouseScroll', fn, false);
1
2
3

# 2.4.2 wheelDelta/detail

ie/chrome : event.wheelDelta上:120;下-120 firefox : event.detail上:-3;下:3

//兼容处理
var b = true;
if (ev.wheelDelta) {
    b = ev.wheelDelta > 0 ? true : false;
} else {
    b = ev.detail < 0 ? true : false;
}
1
2
3
4
5
6
7

# 三、jQuery消除主流浏览器差异

等看源码再议

# 四、IE8支持HTML5标签

  • 通过document.createElement()创建html5新标签。
(function() {
    // 页面头部
    var a = ['section', 'article', 'nav', 'header', 'footer' /* 其他HTML5元素 */];
    for (var i = 0, j = a.length; i < j; i++) {
        document.createElement(a[i]);
    }	
})();
1
2
3
4
5
6
7

# 五、通信

# 5.1 XMLHttpRequest

# 5.1.1 兼容性

  • IE8/IE9、Opera Mini 完全不支持xhr对象
  • IE10/IE11部分支持,不支持 xhr.responseTypejson
  • 部分浏览器不支持设置请求超时,即无法使用xhr.timeout
  • 部分浏览器不支持xhr.responseTypeblob

# 5.2 CORS

IE8、IE9不兼容,其余浏览器都支持。

  • 解决方案:代理devServer.proxy (opens new window)

    webpack 的 devServer.proxy 的功能是由 http-proxy-middleware (opens new window) 项目来实现的

    实现原理是将目标位置的请求代理为前端服务本地的请求,既然是代理成为本地的请求,就不存在跨域的问题,axios 就会用回 XMLHttpRequest 对象进行数据请求,一切都恢复正常了,header、cookies、content-type、authentication 等内容都被正确传递到服务端。