인터프리터 모드(Interpreter): 구문 형식을 정의하고 프로그램 해석을 통해 실행하며 해당 작업을 완료합니다. 프런트 엔드 프로그래밍 시나리오에서는 CSS 선택기를 해석하여 DOM 요소를 선택하는 데 인터프리터 모드를 적용할 수 있습니다.
개방 및 폐쇄 원칙: 객체 지향의 개방 및 폐쇄 원칙은 클래스나 모듈이 확장에는 개방되고 수정에는 폐쇄되어야 한다는 것입니다. 클래스 선택기가 구현되어 있는데, 나중에 속성 선택기가 필요하면 속성 선택기를 정의하여 해당 메소드를 구현하고, 해당 브랜치를 추가하여 단순 팩토리에 속성 선택기 객체를 생성합니다.
일치 원칙: 브라우저는 CSS 선택기를 오른쪽에서 왼쪽으로 일치시키므로 자체 DOM 선택기를 구현할 때 일치 동작은 브라우저의 기본 일치 동작과 일치해야 합니다.
코드:
(함수(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 || 🎜>if(!simple.test(query) && context.querySelectorAll){
return context.querySelectorAll(query);
}else {
//调사용자정义选择器
returninterpret( 쿼리, 컨텍스트);
}
}
//解释执行dom选择符
function explain(query, context){
var parts = query.replace(/s /, " " ).split(" ");
var part = parts.pop();
var selector = Factory.create(part)
var ret = selector.find(context); (parts[0] && ret[0]) ? filter(parts, ret) : ret
}
//ID选择器
function IDSelector(id) {
this.id = id .substring(1);
}
IDSelector.prototype = {
find: 함수(컨텍스트) {
return document.getElementById(this.id);
},
일치: 함수(요소){
return element.id == this.id;
}
};
IDSelector.test = 함수(선택기) {
var regex = /^#([w-_] )/;
regex.test(선택기)를 반환합니다.
};
//元素选择器
function TagSelector(tagName) {
this.tagName = tagName.toUpperCase();
}
TagSelector.prototype = {
find: 함수(컨텍스트) {
return context.getElementsByTagName(this.tagName);
},
일치: 함수(요소){
return this.tagName == element.tagName.toUpperCase() || this.tagName === "*";
}
};
TagSelector.test = 함수(선택기) {
var regex = /^([w*-_] )/;
regex.test(선택기)를 반환합니다.
};
//类选择器
function ClassSelector(className) {
var Splits = className.split('.');
this.tagName = 분할[0] || 한정되지 않은 ;
this.className = 분할[1];
}
ClassSelector.prototype = {
find: 함수(컨텍스트) {
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){
요소를 반환합니다.
}
for(var i=0,n=elements.length; iif( selector.match(elements[i]) ){
ret.push( 요소[i]);
}
}
} else {
elements = selector.find(context);
for(var i=0, n=elements.length; iif( this.match(elements[i]) ) {
ret.push(elements[i] );
}
}
}
return ret;
},
일치: 함수(요소){
var className = this.className;
var regex = new RegExp("^|\s" className "$|\s");
return regex.test(element.className);
}
};
ClassSelector.test = 함수(선택기) {
var regex = /^([w-_] )?.([w-_] )/;
regex.test(선택기)를 반환합니다.
};
//TODO:属性选择器
function AttributeSelector(attr){
this.find = function(context){
};
this.match = function(element){
};
}
AttributeSelector.test = 함수(선택기){
var regex = /[([w-_] )(?:=([w-_] ))?]/;
regex.test(선택기)를 반환합니다.
};
//根据父级元素过滤
function filter(parts, nodeList){
var part = parts.pop();
var 선택기 = Factory.create(part);
var ret = [];
var 부모;
for(var i=0, n=nodeList.length; iparent = nodeList[i].parentNode;
while(parent && parent !== doc){
if(selector.match(parent)){
ret.push(nodeList[i]);
휴식;
}
부모 = parent.parentNode;
}
}
부품 반품[0] && ret[0] ? 필터(부분, ret) : ret;
}
//根据查询选择符创建상应选择器对象
var Factory = {
create: function (query) {
if (IDSelector.test(query)) {
새 IDSelector(쿼리)를 반환합니다.
} else if (ClassSelector.test(query)) {
return new ClassSelector(query);
} else {
새 TagSelector(쿼리)를 반환합니다.
}
}
};
ns.dom || (ns.dom = {});
ns.dom.get = api;
}(이것));