preface
覺得自己去寫一些類,你真的會找到自己不足的地方。其實厲害不是你實現一個類,而是你如何去設計一個類,能讓開發人員更加容易操作。對於這個操作樣式,可以通過javascript訪問style,可是在《javascript進階程式設計》中有講到這樣子CSS、javascript、HTML耦合度太高,不太適合維護;還有就是通過className,但是我們知道className是一個可以被開發人員讀寫的字串,如果要增刪查改元素對應的className的話,可以實現,但是比較麻煩。這個時候HTML5站出來了,提出了classList類,確實方便我們開發人員去使用,但是它有一個弊端就是相容性不是很好。
introduction
-
簡單介紹element.classList,下面是它的4個方法
-
1 add a class to an element's list of classes(為元素添加class)
-
2 remove a class from an element's list of classes(刪除元素的class)
-
3 toggle the existence of a class in an element's list of classes ◦See below about the optional second argument.(切換元素的class)
-
4 check if an element's list of classes contains a specific class(檢查元素是否有這個class)
確實覺得這樣的API讓開發人員少做很多苦力活,詳細的可以去看element.classList,畢竟上面不是我想深入瞭解的知識點,我想深入瞭解的是,自己先去模仿別人設計的API,看自己能不能擴充那個API(很顯然自己還沒達到那種程度)。
description
在這裡說明下我定義的CSSClassList可以到我《javascriptRegex "\b"問題》找,這裡我就不詳述了。我們主要還是來實現上面說的4個方法,可以在不支援classListAPI的瀏覽器上用
-
一 contains方法(個人覺得這個方法是最重要的,之後的add remove和toggle方法都要用到)
-
CSSClassList.prototype.contains = function(cls) {
var classname = this.el.className, reg = new RegExp("\\b" + cls + "\\b");
return reg.test(classname);
}
-
遇見的問題:
- 1 在《javascriptRegex "\b"問題》其實有提到一個比較容易忽略的問題就是對於字串"\b"與"\\b"的區別。
- 2 如何將一個字串轉換成Regex
-
解決問題(1就是對應上面的問題1,以此類推)
- 1 在《javascriptRegex "\b"問題》有說道,這裡不再詳述。
- 2 在我腦海中現在有兩種方法,一種是用eval,但是因為安全性還有效能問題被我否決了,所以我改成了第二種方法是用RegExp建構函式。如果對於現在正在讀我的blog的您來說,有更好的方法請告訴我,大家來交流交流。
-
二 add方法
-
CSSClassList.prototype.add = function(cls) {
var classname = this.el.className;
if (this.contains(cls))
return;
else {
var arr = classname.split(/\s+/);
arr.push(cls);
this.el.className = arr.join(" ");
}}
-
設計思路:
如果在該元素中找到class的話,就不添加了。找不到就添加,如何去添加?我把該元素的className字元 串轉成數組,然後使用數組的push方法並把數群組轉換成字串賦值給該元素的className
-
遇見的問題:
- 對於字串的split方法不是很熟練,比如上面有句代碼我寫成了var arr = classname.split("/\s+/");記住在split參數中是Regex但是我又畫蛇添足加了雙引號""。
-
解決問題:
-
三 remove方法(這個方法還是我折騰比較久的)
-
CSSClassList.prototype.remove = function(cls) {
var classname = this.el.className;
if (!this.contains(cls))
return -1;
else {
//indexOf還是有相容性問題
var arr = classname.split(/\s+/), index = arrIndexOf(arr, cls);
arr.splice(index, 1);
this.el.className = arr.join(" ");
return (this.el.className);
}
}
-
設計思路:找不到要刪除的class就返回-1,然後確定該元素有這個class,就要去找那個class是在哪,然後把它刪除掉。還是那樣子先把該元素的className轉換成數組,然後可以用到ES5的Array.prototype.indexOf方法找到class對應的下標,但是被我否決了,因為這個indexOf只能在IE9+才能用,如過IE9+能用的話,其實就沒必要去實現山寨的classList,因為IE9+本身就支援,那怎麼辦?下面會詳述。找到對應的下標就用數組的splice去刪除該class並把刪除後的數群組轉換成字串賦給該元素的className
-
遇到問題
- 主要還是怎麼用原生的javascript去實現indexOf方法?
-
解決問題
function arrIndexOf(arr, searchEl) {
if (arr.indexOf) {
return arr.indexOf(searchEl);
} else {
for (var i = 0, len = arr.length; i < len; i++) {
if (arr[i] === searchEl)
return i;
}
return -1;
}
}
就不用我過多去解釋了吧,應該看完代碼很容易懂吧,我也不是什麼大牛級,所以我寫的代碼還是很平易近人的。
-
四 toggle方法
-
CSSClassList.prototype.toggle = function(cls) {
if (!this.contains(cls))
this.add(cls);
else
this.remove(cls);
}
這個就不說了,一看就知道了。
summary
在寫這個類的時候確實還是遇到很多問題,但是總是能一一解決。我覺得一個程式員最重要的是他的解決問題的能力吧。畢竟自己寫的類也不是很多,可能是自己的處女作吧,還是會有許多問題出現的,有空的話,我會看看其他大牛寫的代碼,然後兩者再比較,有對比才有差距才有進步。