項目中如果應用了常用的javascript類庫,多數情況下,這些已經封裝好的類庫,都會封裝一個類似於addClass和removeClass的方法,以便於我們對DOM節點的class進行操作。
以jQuery為例:
$(dom).addClass("a").removeClass("b");
由於是封裝好的方法,我們甚至都不需要檢查需要操作的class在DOM中是否存在,用起來的感覺真的是不要太爽。
那么如果項目中沒有使用任何類庫呢,完全原生JavaScript,如何操作DOM節點的class呢?
以不做任何封裝庫為例,僅僅是封裝兩個簡單的函數:
// 添加class function addClass(kls, dom) { var klsReg = new RegExp(kls, 'ig'); for (var i = 0; i<dom.length; i++){ var node = dom[i]; var klses = node.className; if (!klsReg.test(klses)) { node.className = klses + ' ' +kls } console.log(klses) } } addClass("a", ops) // 刪除class function removeClass(kls, dom) { var klsReg = new RegExp(kls, 'ig'); for (var i = 0; i<dom.length; i++){ var node = dom[i]; var klses = node.className; if (klsReg.test(klses)) { node.className = node.className.replace(kls, '') } } } removeClass("red", ops)
其實也沒什么可以疑惑的地方,也就是使用正則表達式對所需要操作的DOM節點進行判斷,如果不存在class名為"a",則直接添加,否則忽略;如果是刪除class的話,如果存在需要刪除的class "b",則刪除對應的b。
在封裝個人類庫中,這里需要注意的是,函數需要作為對象prototype的方法,並且返回該對象,以用於連綴的寫法。
在html5的API中提供了一種新的寫法,完全擺脫了正則表達式(意思是不在需要我們自己寫正則表達式了):
var ops = document.querySelectorAll("p") for (let p of ops) { p.classList.add("blue"); p.classList.remove("red"); }
需要注意的是,classList這種API是不支持連綴寫法的。
element.classList還有另外三個方法:
item ( Number )按集合中的索引返回類值。
toggle ( String [, force] )當只有一個參數時:切換 class value; 即如果類存在,則刪除它並返回false,如果不存在,則添加它並返回true。
當存在第二個參數時:如果第二個參數的計算結果為true,則添加指定的類值,如果計算結果為false,則刪除它。第二個參數的兼容性並不是特別好。
contains ( String )檢查元素的類屬性中是否存在指定的類值。
var ops = document.querySelectorAll("p") for (let p of ops) { p.addEventListener("click", function () { this.classList.toggle("blue") }, false) }
其實仔細看這幾個方法,會發現,與jQuery中的addClass, removeClass, toggleClass, contains非常相似,在一定程度上,也能夠方便我們加深對這幾個方法的理解。