JavaScript實現自己的DOM選取器原理及代碼

來源:互聯網
上載者:User

解譯器模式(Interpreter):定義一種文法格式,通過程式解釋執行它並完成相應的任務。在前端編程情境中可以應用解譯器模式來解釋CSS選擇符實現DOM元素的選擇。

開放封閉原則:物件導向中的開放封閉原則是類或模組應該對擴充開放對修改封閉,在這個dom選取器中實現id選取器,元素選取器,類別選取器,如果以後需要屬性選取器的話定義一個屬性選取器實現相應的方法,同時在簡單工廠中增加相應的建立屬性選取器對象分支即可。

匹配原理:瀏覽器在匹配CSS選擇符時是按照從右至左匹配的,所以實現自己的DOM選取器時匹配行為也應該和瀏覽原生匹配行為一致。

代碼: 複製代碼 代碼如下:(function (ns) {
/*
//tagName
console.log(dom.get("p"));
//#id
console.log(dom.get("#div"));
//.class
console.log(dom.get(".span", document.body));
//tag.class
console.log(dom.get("div.span"));
//#id .class
console.log(dom.get("#div .span"));
//.class .class
console.log(dom.get(".ul .li-test"));
*/
var doc = document;
var simple = /^(?:#|\.)?([\w-_]+)/;
function api(query, context) {
context = context || doc;
//調用原生選取器
if(!simple.test(query) && context.querySelectorAll){
return context.querySelectorAll(query);
}else {
//調用自訂選取器
return interpret(query, context);
}
}
//解釋執行dom選擇符
function interpret(query, context){
var parts = query.replace(/\s+/, " ").split(" ");
var part = parts.pop();
var selector = Factory.create(part);
var ret = selector.find(context);
return (parts[0] && ret[0]) ? filter(parts, ret) : ret;
}
//ID選取器
function IDSelector(id) {
this.id = id.substring(1);
}
IDSelector.prototype = {
find: function (context) {
return document.getElementById(this.id);
},
match: function(element){
return element.id == this.id;
}
};
IDSelector.test = function (selector) {
var regex = /^#([\w\-_]+)/;
return regex.test(selector);
};
//元素選取器
function TagSelector(tagName) {
this.tagName = tagName.toUpperCase();
}
TagSelector.prototype = {
find: function (context) {
return context.getElementsByTagName(this.tagName);
},
match: function(element){
return this.tagName == element.tagName.toUpperCase() || this.tagName === "*";
}
};
TagSelector.test = function (selector) {
var regex = /^([\w\*\-_]+)/;
return regex.test(selector);
};
//類別選取器
function ClassSelector(className) {
var splits = className.split('.');
this.tagName = splits[0] || undefined ;
this.className = splits[1];
}
ClassSelector.prototype = {
find: function (context) {
var elements;
var ret = [];
var tagName = this.tagName;
var className = this.className;
var selector = new TagSelector((tagName || "*"));
//支援原生getElementsByClassName
if (context.getElementsByClassName) {
elements = context.getElementsByClassName(className);
if(!tagName){
return elements;
}
for(var i=0,n=elements.length; i<n; i++){
if( selector.match(elements[i]) ){
ret.push(elements[i]);
}
}
} else {
elements = selector.find(context);
for(var i=0, n=elements.length; i<n; i++){
if( this.match(elements[i]) ) {
ret.push(elements[i]);
}
}
}
return ret;
},
match: function(element){
var className = this.className;
var regex = new RegExp("^|\\s" + className + "$|\\s");
return regex.test(element.className);
}
};
ClassSelector.test = function (selector) {
var regex = /^([\w\-_]+)?\.([\w\-_]+)/;
return regex.test(selector);
};
//TODO:屬性選取器
function AttributeSelector(attr){
this.find = function(context){
};
this.match = function(element){
};
}
AttributeSelector.test = function (selector){
var regex = /\[([\w\-_]+)(?:=([\w\-_]+))?\]/;
return regex.test(selector);
};
//根據父級元素過濾
function filter(parts, nodeList){
var part = parts.pop();
var selector = Factory.create(part);
var ret = [];
var parent;
for(var i=0, n=nodeList.length; i<n; i++){
parent = nodeList[i].parentNode;
while(parent && parent !== doc){
if(selector.match(parent)){
ret.push(nodeList[i]);
break;
}
parent = parent.parentNode;
}
}
return parts[0] && ret[0] ? filter(parts, ret) : ret;
}
//根據查詢選擇符建立相應選取器對象
var Factory = {
create: function (query) {
if (IDSelector.test(query)) {
return new IDSelector(query);
} else if (ClassSelector.test(query)) {
return new ClassSelector(query);
} else {
return new TagSelector(query);
}
}
};
ns.dom || (ns.dom = {});
ns.dom.get = api;
}(this));

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.