若是咱們把元素的類名操做比做「切水果」遊戲的話,其中一個單獨的類名就比如「水果」或「炸彈」!android
DOM Level 2時代,類名的獲取與設置,多半使用className
屬性,className
的生效近似切水果的「一刀切」。在web的初期,交互什麼的其實很簡單的來;就像切水果剛開始的時候,一次就一個水果飛上來,一刀「咔嚓」切了就好,就像使用className
賦個類名值,就算偶爾冒出2個水果,className
也能夠一刀切搞定的。ios
可是,隨着web的發展,交互的逐漸複雜,一次出現的水果愈來愈多,已經不是className
一刀就能夠搞定的了;並且,還有炸彈,className
一刀切可能就自尋死路了。web
爲了應對這種需求,顯然HTML5要作點什麼,因而classList
API出現了,能夠有針對性地切水果,不會碰到炸彈什麼的……數組
這就是事情從className
發展到classList
的原因與過程。瀏覽器
classList
雖改進,可是,從效果上講,仍是敵不過jQuery等外掛,後面會提到。app
classList
實際上已經出現好多年了,所以,天然,FireFox瀏覽器,Chrome瀏覽器都支持的很。IE家族中,從IE10瀏覽器開始纔開始承認classList
能進能退的非一刀切作法。框架
手機上,Android 3.0+以上纔開始支持,哦,該死,這很糟糕。如今手機web app要求android 2.*也要支持。dom
截止今日,兼容性見下截圖:函數
因而可知,在PC上,若是要判斷是不是IE10+以及其餘現代瀏覽器,能夠試試:document.body.classList
是否爲undefined
學習
假設有這麼個空白頁面:
<body class="a b c"></body>
在Firebug以及Chrome控制檯中,運行:
document.body.classList
返回的分別是:
可見其直接暴露的API有:
document.body.classList.item(0);
結果是:"a"
.
若是索引超出範圍,例如:
document.body.classList.item(3);
結果是:null
.
document.body.classList.add("c"); document.body.classList.length // 3
此函數方法執行的返回值是undefined
, 所以,classList
的add()
方法是沒法級聯的。下面的remove()
方法也是如此。
document.body.classList.remove("c"); document.body.classList.length // 2
有點對應於jQuery中的removeClass()
方法,而後者返回包裝器對象自己,可級聯;這裏的remove()
方法返回undefined
.
false
; 若是沒有,則添加該類名,並返回true
. 更新於當日
部分現代瀏覽器,例如Chrome瀏覽器以及Firefox 24的toggle()
方法已經支持第2個參數,.toggle(token, switch)
. 其中參數switch
爲Boolean類型值,若是爲true
表示添加,若是爲false
則表示移除。並返回該Boolean值。
hasClass
方法,注意,這裏的是contains
而不是contain
,後面有個s
哦! 返回值很易懂的。若是包含,則返回true
, 不包含,則false
. 例如:
document.body.classList.contains("c"); // false 由於"c"上面remove掉了
在Firebug控制檯結果中,咱們還看到了toString()方法。實際上,Chrome瀏覽器也有(未直接顯示),IE10也有,不過,彷佛來自層級更高對象的繼承。從下面截圖中的屬性顏色區分可見一斑:
就做用上講,等同於className
. 例如:
document.body.classList.toString() === document.body.className; // true
classList
的返回值顯示,其本質上是DOMTokenList
– DOM標記列表.
DOMTokenList
這種類型表示一組空間分隔的標記。一般由HTMLElement.classList
,HTMLLinkElement.relList
,HTMLAnchorElement.relList
或HTMLAreaElement.relList
返回。從0開始的類JavaScript數組索引。DOMTokenList
始終是區分大小寫的。
在FireFox以及Chrome下,咱們執行typeof DOMTokenList
的結果是:"function"
; 可是在IE10下,倒是:"object"
.
同時雖然typeof
結果爲"function"
,可是執行DOMTokenList()
會報」Illegal constructor」錯誤;IE10執行DOMTokenList()
也會報錯,錯誤是」缺乏函數」。
所以,試圖經過typeof obj == "function"
來判斷obj
就是個函數的作法是不徹底正確的。
classList
除了上面提到的不能級聯這個無關痛癢的侷限外,還有個比較頭疼的侷限,就是不能一次add
或remove
或toggle
多個類名。//zxx: 級聯指的是$().a().b().c()這種能夠連在一塊兒調用方法的寫法。
例如:
document.body.classList.add("c d"); // Error: String contains an invalid character document.body.classList.add("c\x20d"); // Error: String contains an invalid character document.body.classList.remove("c d"); // Error: String contains an invalid character
咱們要想多類名處理,須要一個一個來,例如:
var clList = document.body.classList; clList.add("d"); clList.add("e"); clList.toString(); // "a b c d e"
這一點來看,原生的classList
API要比jQuery或MooTools等框架的addClass/removeClass/...
等類名相關外掛方法弱爆了。然而,classList
API沒有戀愛經歷、很是單純。所以,雖然胸小了一點;可是,富豪就是喜歡之。
add
的參數個數限制等方法比如生孩子,一次只能生一個,這符合國家要求符合規範。可是,有些有錢人,就像張藝謀,就愁孩子少,恨不能一次生他3個,咋辦呢?咱們能夠試試對classList
作擴展,例如擴展一個adds
方法,能夠一次添加多個類名,多個類名以空格分隔:
DOMTokenList.prototype.adds = function(tokens) { tokens.split(" ").forEach(function(token) { this.add(token); }.bind(this)); return this; }; // 看看能不能一會兒生3個孩子 var clList = document.body.classList; clList.adds("child1 child2 child3").toString(); // "a b c child1 child2 child3"
這樣,只要肚子夠大,想生幾個就能夠生幾個了,中國足球說不定就有但願了——11胞胎爭霸全球!
其餘些方法,您能夠作相似擴展。
可是,平心而論,單類名一個一個添加雖然苦逼了點,可是,我的情感上,由於原汁原味,更喜歡!
//zxx: ios4彷佛並未支持bind
方法,所以,上面的擴展若是在手機上使用,需稍做調整。
隨着JS API的愈來愈豐富,以及愈來愈多在現代瀏覽器、尤爲手機上的一些折騰,讓我愈來愈疑惑一些龐大框架的存在乎義。
有人可能會提出:原生的API方法名太長了,例如:addEventListener
, getComputedStyle
, insertAdjacentHTML
,getBoundingClientRect
等。
1. 關於「名字長,很差記」
你父母手機號是?啊,不知道啊!那確實名字太長,不太好記。
2. 關於「文件大啊」
小明工做40年,交的養老保險金有100萬,0存款,每月能夠拿4000, 每個月結餘2000; 大明工做40年,養老保險一分錢沒交,存了100萬,每個月結餘-3000。結果,小明笑大明每月的開銷比他多1000塊,說你沒交養老保險虧大了。
dom.addEventListener
和$(dom).bind
哪一個字符多,顯然前者,小明你贏了!
那下面代碼呢?
var addEventListener = "addEventListener"; dom[addEventListener] var bind = "bind"; $(dom)[bind]
小明,你又贏了!JS壓縮以後呢?
var a= "addEventListener"; dom[a] var b= "bind"; $(dom)[b]
小明,你又贏了!那多調用幾回呢?
var a= "addEventListener"; dom[a] dom[a] dom[a] dom[a] dom[a] var b= "bind"; $(dom)[b] $(dom)[b] $(dom)[b] $(dom)[b] $(dom)[b]
同樣多,小明,你還沒輸!好吧,我再次認爲你是對的。
3. 關於「新人很差上手」
林遠圖封裝了《葵花寶典》,美名曰「辟邪劍法」,比較好上手,結果呢,其兒孫泛泛。卻是林平之,學習了盜版原生的《葵花寶典》,雖然很差上手(要咬抹布揮刀那個),可是,結果秒了餘滄海,也算高手之列了。
啊?原來你是招新人來打雜的,sorry, 網上的框架、插件確實比較適合大家。
zepto.js算是蠻簡潔的移動框架了,實際上,(糾正:zepto.js
有借鑑jqmobi.js
(以前被intel收購,更名爲appframework
)的嫌疑zepto.js
是被jqmobi.js
借鑑),然後者彷佛更小,我看了下,gzip後6.7K
, 小於前者9.7k
(因含touch
相關事件重寫). 可是,我我的看來,仍是太大了,尤爲那些DOM相關的API,都統統會孃家去吧,gzip後2~3K
足矣。
天氣很熱,想釣魚了!