瀏覽器佔比現狀
在各大瀏覽器廠商的發展過程當中,他們其實對web的標準都有不一樣的實現,由於實現的標準的不一樣,因此會有兼容性的產生,早期IE是在瀏覽器的世界中,佔據主導地位。因此它自身實現了不少不一樣於標準瀏覽器的東西,有css的,也有js的。css
從IE8開始,IE瀏覽器漸漸遵循標準,到IE9後因爲你們都一致認爲標準很重要,能夠說在兼容性上比較好了,可是在中國來講,因爲xp的佔有率問題,仍是有不少xp系統ie七、8瀏覽器。
國家互聯網應急中心(CNCERT)2018年第四季度國內操做系統及瀏覽器佔比狀況分析:
js兼容問題及解決
一、js中 style、currentStyle和getComputedStyle的區別
1.1
style
:各大瀏覽器都兼容,能設置樣式和獲取樣式,可是獲取不了外部樣式。
寫法:ele.style.attr(這樣爲獲取),ele.style.attr="值";
1.2.
currentStyle
:該屬性只兼容IE,不兼容火狐和谷歌
ele.currentStyle.attr
;
1.3.
getComputedStyle
:該屬性是兼容火狐谷歌,不兼容IE8及如下
window.getComputedStyle(ele,null).attr
一般使用
getComputedStyle
讀取樣式,經過
element.style
修改樣式。
可選[pseudoElt]屬性:指定一個要匹配的僞元素的字符串。不須要僞元素能夠爲null
配合該屬性能夠從僞元素拉取樣式信息:好比,
::after, ::before
getComputedStyle(oDiv, '::after').content;
html
//兼容性寫法:
function getStyle(ele,attr){
html5
if(ele.currentStyle){
css3
return ele.currentStyle[attr]
web
}else{
正則表達式
return getComputedStyle(obj,false)[attr]
chrome
}
瀏覽器
}
框架
2. 使用event對象
以主流瀏覽器 IE、谷歌、火狐爲例:
(1) IE 在IE中,event 是一個全局的變量,不存在做用域的問題。也就是說,誰觸發了事件,那在事件綁定的函數中,你能夠直接使用event的屬性作任何操做,沒有做用域的限制,也沒有其餘函數格式的要求。
(2)Chrome 谷歌 谷歌作的也不錯,使用也沒有什麼問題。在 Chrome 中,event並非全局變量。他是在每一個事件綁定的函數中都默認傳入了一個形參event,注意函數的第一個形參就是event對象,並且咱們不須要去寫這個形參。若是你要在事件綁定的函數中使用 event,那直接 event . 點他的屬性便可。系統默認將event對象以參數的形式傳遞到了函數中。這裏不須要你作任何操做,只管用,簡單粗暴。
IE 和 Chrome 雖然看起來用法同樣,其實仍是有本質區別的,只是瀏覽器封裝的好而已。
(3)Firebox 火狐 火狐就麻煩一點了。由於火狐中壓根就沒有event這個變量。不過解決方法也是很簡單的:
1.2.1 用戶不傳參:
想要使用 event,咱們就須要先使用以下語句
var e = arguments.callee.caller.arguments[0] || window.event
arguments.callee.caller.arguments[0]:
函數體自己-->函數體的調用函數體--> function onclick()
argument.callee.caller.arguments[0]
即爲傳參集合的第一個形參event了.
1.2.2. 傳參(event)
3.獲取目標元素:
兼容寫法:
event.srcElement ? event.srcElement : event.target;
srcElement:ie
4. attachEvent和addEventListener
4.1 attachEvent是IE有的方法,它不遵循W3C標準,而其餘的主流瀏覽器如FF等遵循W3C標準的瀏覽器都使用addEventListener,因此實際開發中需分開處理。
4.2 屢次綁定後執行的順序是不同的,attachEvent是後綁定先執行,addEventListener是先綁定先執行。
ele.attachEvent('onclick',function(){
console.log('test...')
dom
})//ie11以及以上不支持 chrome不支持 ff不支持
ele.addEventListener("click",function(){
console.log('ceshi...')
},false) //ie8及如下 不支持
5. 獲取dom節點:
parentElement
獲取對象層次中的父元素。
parentNode
獲取文檔層次中的父結點。
在Dom文檔結構中,HTML頁面每一部分都是由節點組成的,節點的類型一共有3種,元素節點,文本節點,屬性節點,從圖中能夠看出屬性節點屬於元素節點的分支,通常不常考慮。
二者在一般狀況下都是同樣的,由於包含元素的節點只有多是元素節點,這裏可能會有一個誤區,有些人可能會想文本節點是否能夠包含元素節點,來做爲父節點,這裏是不行的,文本節點只是文本自己,自身算一個節點,文本節點的父節點直接是元素節點。
兩者惟一區別:
由於
parentElement
找的是
元素,所以當找到根部document時候就是出現值爲null的報錯,並且
parentNode
找的是
節點,固然就能夠顯示出來了!
bodyDom.parentNode.parentNode.parentNode.parentNode
---#document
bodyDom.parentElement.parentElement.parentElement.parentElement
---null
六、日期函數處理
IE8如下:
new Date().getFullYear() === new Date().getYear()
:獲得的是當前年份 2019
IE九、標準瀏覽器:
new Date().getYear()
爲 119
:獲得的是當前年份(2019)與1900年的差值 119
七、集合類對象問題
問題說明:IE下,可使用 () 或 [] 獲取集合類對象;Firefox下,只能使用 [ ]獲取集合類對象。
解決方法:統一使用 [] 獲取集合類對象。
八、鼠標按鍵編碼的兼容
W3C標準下:0,1,2分別表明左,中,右三個鍵;
在ie11及以上 + 主流瀏覽器下 是符合W3C標準的,可是在ie10以及如下:
左中右分別爲:1 4 2
function but(evt){
var e = evt || window.event;
if(evt){
return e.button;
} else if (window.event){
switch(e.button){
case 1: return 0;
case 4: return 1;
case 2: return 2;
}
}
}
九、8引出的其它問題:
ie中的
window.event
全局對象和 事件訪問對象(傳遞的參數evt) 的區別:
1.DOM標準描述了一個Event對象,提供了觸發事件的元素信息,並容許在腳本中獲取該元素。
2. ie中的事件處理:
ie的全局event對象的屬性不一樣於DOM標準的event對象,但提供的數據相似。
區別:
DOM事件模型與IE事件模型之間的主要區別是事件信息的訪問方式,以及獲取引起事件的元 素的方式。
DOM是須要傳送事件引用給處理函數,IE中直接經過全局的event訪問;
DOM中獲取獲取引起事件的元素對象是經過tarfet屬性,而IE是經過
srcElement
屬性。
css兼容性問題
首先是<!DOCTYPE>的聲明 位於位於HTML文檔中的第一行,處於 <html> 標籤以前。告知瀏覽器的解析器用什麼文檔標準解析這個文檔。DOCTYPE不存在或格式不正確會致使文檔以兼容模式呈現。
標準模式的排版 和JS運做模式都是以該瀏覽器支持的最高標準運行。在兼容模式中,頁面以寬鬆的向後兼容的方式顯示,模擬老式瀏覽器的行爲以防止站點沒法工做。
一、reset
最主要也是最多見的,就是瀏覽器對標籤的默認支持不一樣,因此咱們要統一,就要進行CSS reset 。可是不要爲了reset而reset:
可是不少時候咱們的CSS reset過於臃腫,主要有兩個問題:
1.1 把不少瀏覽器對元素的默認屬性有設置了一邊,好比div的padding和margin爲0啊什麼的,這是沒有必要的
1.2 把一些很不經常使用的元素的設置也寫進了CSS reset。
二、上下margin重合問題
相鄰的兩個div margin-left margin-right 不會重合,但相鄰的margin-top margin-bottom會重合。
三、td高度的問題
table中td的寬度都不包含border的寬度,可是oprea和ff中td的高度包含了border的高度 。
解決: 設置line-height和height同樣。在ie中若是td中的沒有內容,那麼border將不會顯示。
四、兼容ie8 或者ie9 或任意ie版本瀏覽器
4. 1.條件註釋法(IE10+已經不支持條件註釋)
大於 gt || 大於等於 gte || 小於 lt || 小於等於 lte(
<!--[if gte IE 8]><![endif]-->
)
用ie瀏覽器獨有的文檔註釋的方式。像這樣:
<!DOCTYPE html>
<!--[if IE 8 ]> <html class="ie8" lang="en"> <![endif]-->
<!--[if IE 9 ]> <html class="ie9" lang="en"> <![endif]-->
<!--[if (gt IE 9)|!(IE)]><!-->
<html lang="en"> <!--<![endif]-->
能夠獨立的維護處理兼容ie瀏覽器的樣式表,又不會淹沒在一大堆css hack標識中,只須要在獨立對ie8應用樣式規則的地方
4.2. 非IE(IE10+也能識別),此處多加的<-->,在IE中被看成內部註釋,而在非IE瀏覽器中會閉合以前的註釋(<!--[if !IE]><--><![endif]-->)
<!--[if !IE]><-->
<div class="box" id="box"></div>
<![endif]-->
五、對於360雙核瀏覽器
能夠添加如下頭部meta信息可使得網頁用webkit內核渲染:
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
IE=edge:保持使用最高級別模式顯示內容;
chrome=1:谷歌的外掛插件Google Chrome Frame(谷歌內嵌瀏覽器框架GCF),使用IE瀏覽網頁時其實是使用Chrome瀏覽器內核渲染,最低支持IE6,但前提是客戶端已經安裝GCF。
但實際上這個meta標識是ie瀏覽器所識別的,並非公認的標準,因此有時你會發現360並不能老是以chrome內核渲染你的按現代標準開發的網頁。
能夠試試經過添加:
<meta name="renderer" content="webkit">
六、ie8的css兼容
6.1 使用meta標籤調節瀏覽器的渲染方式:
IE8中有一個「兼容性視圖」的概念,當初IE8發佈時,相對於IE6/7已經作出了很是大的改進,可是不少老站點僅針對IE6/7進行了優化,使用IE8渲染反而會一團糟。IE8加入了「兼容性視圖」功能,這樣的話就能夠在IE8中使用IE6或IE7的內核渲染頁面。這個固然不是咱們想要的,因此須要使用meta標籤來強制IE8使用最新的內核渲染頁面,代碼以下:
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
IE=edge表示強制使用IE最新內核,
chrome=1表示若是安裝了針對IE6/7/8等版本的瀏覽器插件Google Chrome Frame(可讓用戶的瀏覽器外觀依然是IE的菜單和界面,但用戶在瀏覽網頁時,實際上使用的是Chrome瀏覽器內核),那麼就用Chrome內核來渲染。
對比360:
<meta name="renderer" content="webkit">
6.2 ie8中的一些css 不支持
6.2.1 ie8支持:
first-child
,但不支持:
last-child
。由於前者是css2.1標準,後者是css3標準。
推薦的作法不是使用last-child,而是給最後一個元素設置一個.last的class,而後對此進行樣式設置,這樣就所有兼容了。
6.2.2
html5shiv.js
IE8不支持HTML5的新標籤,如
<header>
、
<nav>
等標籤在IE8沒法渲染。html5shiv.js可幫助IE6-8瀏覽器兼容HTML5語義化標籤。
使用方法:在頁面中引用html5shiv.js文件。必須添加在頁面的<head>元素內,由於IE瀏覽器必須在元素解析前知道這個元素,因此這個js文件不能在頁面底部引用。
6.2.3.
Respond.js
IE8不支持CSS媒體查詢,對響應式設計大大不利。Respond.js可幫助IE6-8兼容「
min/max-width
」媒體查詢條件。
使用方法:在頁面中全部css文件的引用位置以後引用
Respond.js
。並且
Respond.js
的引用得越早,用戶看到頁面閃爍的機會越小。
6.2.4. CSS3字體單位「rem」兼容方案:
rem.js
CSS3引入了新的字體大小單位rem,與em的「相對於其父元素來設置字體大小」的功能不一樣,rem是相對於根元素<html>的字體大小比率單位,成了目前主流的單位之一。IE9+開始支持,IE8就只能經過引入js庫來支持了。
使用方法:在頁面中引用rem.js文件。須要引用在頁腳,也就是<body>末尾,在全部css文件引用和DOM元素以後。
6.2.5. 一些其它不支持的屬性:
border-radius 圓角
box-shadow 盒子陰影
CSS3 Background 背景漸變
七、placeholder
不支持ie10-如下的版本(能夠經過使用一個span標籤來模擬提示。)
關於css優化問題:
一、不要使用*{} 相似的通配符
這種方法雖然寫起來簡單,可是渲染起來,瀏覽器引擎要遍歷全部的標籤,很影響效率。爲了對瀏覽器友好,能夠把本身常常用的標籤進行重置操做。
二、儘可能少用絕對定位和浮動等高性能屬性
雖然絕對定位能夠很簡潔的實現很棒的效果,可是因爲瀏覽器的渲染機制,網頁中若是用過多的絕對定位,會讓網頁加載速度變得很慢。
三、利用CSS繼承減小代碼量
咱們知道有一部分CSS代碼是能夠繼承的,若是父元素已經設置了該樣式,子元素就不須要去設置該樣式,這個也是提升性能的行之有效的方法。
常見的能夠繼承的屬性好比:
color,font-size,font-family,text-align,line-height等等
不可繼承的好比:
position,display,float,display,background。width等等
四、CSS Sprites減小http請求
小圖標 經過一張雪碧圖 控制background-position來請求
五、合寫css:
font
background
padding
margin
六、不要用標籤或 class 來限制 ID 規則
不少人會寫出#test.info或者div#test這樣的選擇器,這個只能說是多此一舉,id已經能夠惟一併且最快的定位一個元素了
七、避免通配選擇器
CSS選擇器對性能的影響源於瀏覽器匹配選擇器和文檔元素時所消耗的時間,因此優化選擇器的原則是應儘可能避免須要消耗更多匹配時間的選擇器。而在這以前咱們須要瞭解CSS選擇器匹配的機制,如例子的子選擇器規則:
#header a {font-weight:blod;}
咱們中的大多數人都是從左到右的閱讀習慣,可能也會習慣性的設定瀏覽器也是從左到右的方式進行匹配規則,由於會推測這條規則的開銷並不高。咱們這樣假象瀏覽器會像這樣的方式工做:找到惟一的id爲header爲的元素,而後把這個樣式規則應用到直系子元素中的a元素上。咱們知道文檔中只有一個id爲header的元素,而且它只有幾個a類型的子節點,因此這個CSS選擇器應該至關高效。
事實上,卻剛好相反,CSS選擇器是從右到左進行規則匹配。瞭解這個機制後,例子中看似高效的選擇器在實際中的匹配開銷是很高的,瀏覽器必須遍歷頁面中全部的a元素而且肯定其父元素的id是否爲header。
若是把例子的子選擇器改成後代選擇器則會開銷更多,在遍歷頁面中全部a元素後還需向其上級遍歷直到根節點。
#header a {font-weight:blod;}
理解了CSS選擇器從右到左匹配的機制後,能夠理解選擇器中最右邊的規則每每決定了瀏覽器繼續左移匹配的工做量,咱們把最右邊選擇規則稱之爲關鍵選擇器。
通配選擇器使用 * 符合表示,可匹配文檔中的每個元素。以下例規則將全部元素的字體大小設置爲20px:
* { font-size:20px;}
通配選擇器做用於全部的元素,如規則最右邊爲通配符:
.selected * {color: red;}
瀏覽器匹配文檔中全部的元素後分別向上逐級匹配class爲selected的元素,直到文檔的根節點,所以其匹配開銷是很是大的,一般比開銷最小的ID選擇器高出1~3個數量級,因此應避免使用關鍵選擇器是通配選擇器的規則。
八、避免單規則的屬性選擇器
屬性選擇器根據元素的屬性是否存在或其屬性值進行匹配,以下例規則會把herf屬性值等於」#index」的連接元素設置爲紅色:
.selected [href=」#index」] {color: red;}
但其匹配開銷是很是大的,瀏覽器先匹配全部的元素,檢查其是否有href屬性而且herf屬性值等於」#index」, 而後分別向上逐級匹配class爲selected的元素,直到文檔的根節點。因此應避免使用關鍵選擇器是單規則屬性選擇器的規則。
九、避免類正則的屬性選擇器
CSS3添加了複雜的屬性選擇器,能夠經過類正則表達式的方式對元素的屬性值進行匹配。固然這些類型的選擇器定是會影響性能的,正則表達式匹配會比基於類別的匹配會慢不少。大部分狀況下咱們應儘可能避免使用 *=, |=, ^=, $=, 和 ~=語法的屬性選擇器。
十、移除無匹配的樣式:
移除無匹配的樣式,有兩個好處:
第一,刪除無用的樣式後能夠縮減樣式文件的體積,加快資源下載速度;
第二,對於瀏覽器而言,全部的樣式規則的都會被解析後索引發來,即便是當前頁面無匹配的規則。移除無匹配的規則,減小索引項,加快瀏覽器查找速度;