jQuery的出現,大大的提升了我們操作dom的效率,使得我們的開發更上一層樓,如jQuery的選擇器就是一個很強大的功能,它包含了類選擇器、id選擇器、屬性選擇器、元素選擇器、層級選擇器、內容篩選選擇器等等,很是方便快捷,並且這些選擇器的兼容性都很好,可以說操作dom使用jq選擇器一時爽,一直使用一直爽!只是,目前Vue、React、Angular三大框架的出現大大降低了JQuery的使用頻率,而且JQuery在操作dom和綁定數據時確實存在一定的性能問題和各種坑,但依舊不可抹殺jq在操作dom方面的強大存在!
說了JQuery這么多的牛逼之處,那么它的很多內部原理是如何實現的呢?今天就來簡單實現一個類似jQuery的類選擇器和name屬性選擇器。
類選擇器:
function getElementsByClass(className) {
var classArr = [];
var tags = document.getElementsByTagName("*");
for (var i = 0; i < tags.length; i++) {
if (tags[i].nodeType == 1) {
if (tags[i].getAttribute("class") == className) {
classArr.push(tags[i]);
}
}
}
return classArr;
}
其實name屬性選擇器跟類選擇器一樣,只是判斷條件稍微變了一下而已:
function getElementsByName(name) {
var nameArr = [];
var num = 0;
var tags = document.getElementsByTagName("*");
for (var i = 0; i < tags.length; i++) {
if (tags[i].nodeType == 1) {
if (tags[i].getAttribute("name") == name) {
nameArr.push(tags[i]);
}
}
}
return nameArr;
}
name屬性選擇器大多用在表單的操作方面。
以上代碼中有一個nodeType的屬性,它是用來判斷節點的類型,nodeType共有12個值,1代表節點元素,2代表屬性,3代表元素或屬性中的文本內容。這三個數值用的是比較多的,其他9個用的不多,想了解的話可以去看一下API。在這里,我們需要得到元素節點,所以就會判斷當前元素的nodeType是否為1。
再來貼一下用遞歸來實現獲取元素的所有子節點(含孫子節點):
/**
* 遞歸獲取所有子節點
*
node代表想要獲取所有子節點的父節點
type取值:
1 Element 代表元素
2 Attr 代表屬性
3 Text 代表元素或屬性中的文本內容
4 CDATASection 代表文檔中的 CDATA 部分(不會由解析器解析的文本)
5 EntityReference 代表實體引用
6 Entity 代表實體
7 ProcessingInstruction 代表處理指令
8 Comment 代表注釋
9 Document 代表整個文檔(DOM 樹的根節點)
10 DocumentType 向為文檔定義的實體提供接口
11 DocumentFragment 代表輕量級的 Document 對象,能夠容納文檔的某個部分
12 Notation 代表 DTD 中聲明的符號
*/
var allChildNodes = function (node, type) {
// 1.創建全部節點的數組
var allCN = [];
// 2.遞歸獲取全部節點
var getAllChildNodes = function (node, type, allCN) {
// 獲取當前元素所有的子節點nodes
var nodes = node.childNodes;
// 獲取nodes的子節點
for (var i = 0; i < nodes.length; i++) {
var child = nodes[i];
// 判斷是否為指定類型節點
if (child.nodeType == type) {
allCN.push(child);
}
getAllChildNodes(child, type, allCN);
}
}
getAllChildNodes(node, type, allCN);
// 3.返回全部節點的數組
return allCN;
}
// 調用:
// 獲取body中全部節點
allChildNodes(document.querySelector('body'), 1);
//獲取body中全部純文本節點
allChildNodes(document.querySelector('body'), 3)