Ext源码解析:2, DomQuery.js

news/2024/7/10 22:59:49 标签: EXT, 正则表达式, jQuery, Cache, Mootools
from[url]http://www.beyondrails.com/blogs/19/edit[/url]

在[url=http://www.beyondrails.com/blogs/14]Extjs Introduction[/url]中提到:
[quote]
DomQuery is 2~3 times faster than jQuery/dojo/Mootools, Prototype is the most slowest one!
[/quote]
Speed Test测试页面: [url=http://extjs.com/playpen/slickspeed/]http://extjs.com/playpen/slickspeed/[/url]

[color=Red]Ext的DomQuery为啥这么快呢?[/color]
一是因为DomQuery的byId/byTag/byClassName/byAttribute/byPseudo等基本查询方法实现的比较好
二是因为DomQuery良好的结构和模块设计
三是因为DomQuery有一个查询缓存

DomQuery的Dom查询器分四种类型:
1,Element Selector
2,Attribute Selector
3,Pseudo Class Selector
4,CSS Value Selector

Ext的查询方法是Ext.query(String selector, [Node root]) : Array
[code]
Ext.query = Ext.DomQuery.select;
[/code]
select方法的实现:
[code]
select : function(path, root, type){
if(!root || root == document){
root = document;
}
if(typeof root == "string"){
root = document.getElementById(root);
}
var paths = path.split(",");
var results = [];
for(var i = 0, len = paths.length; i < len; i++){
var p = paths[i].replace(trimRe, "");
if(!cache[p]){
cache[p] = Ext.DomQuery.compile(p);
if(!cache[p]){
throw p + " is not a valid selector";
}
}
var result = cache[p](root);
if(result && result != document){
results = results.concat(result);
}
}
if(paths.length > 1){
return nodup(results);
}
return results;
}
[/code]
可以看到,Ext对于selector做了一个cache,缓存结果为Ext.DomQuery.compile方法返回的一个function
返回的function接收一个参数root来指示从那个Dom元素开始查询
[code]
compile : function(path, type){
type = type || "select";

var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"];
var q = path, mode, lq;
var tk = Ext.DomQuery.matchers;
var tklen = tk.length;
var mm;

// accept leading mode switch
var lmode = q.match(modeRe);
if(lmode && lmode[1]){
fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
q = q.replace(lmode[1], "");
}
// strip leading slashes
while(path.substr(0, 1)=="/"){
path = path.substr(1);
}

while(q && lq != q){
lq = q;
var tm = q.match(tagTokenRe);
if(type == "select"){
if(tm){
if(tm[1] == "#"){
fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';
}else{
fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';
}
q = q.replace(tm[0], "");
}else if(q.substr(0, 1) != '@'){
fn[fn.length] = 'n = getNodes(n, mode, "*");';
}
}else{
if(tm){
if(tm[1] == "#"){
fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';
}else{
fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';
}
q = q.replace(tm[0], "");
}
}
while(!(mm = q.match(modeRe))){
var matched = false;
for(var j = 0; j < tklen; j++){
var t = tk[j];
var m = q.match(t.re);
if(m){
fn[fn.length] = t.select.replace(tplRe, function(x, i){
return m[i];
});
q = q.replace(m[0], "");
matched = true;
break;
}
}
// prevent infinite loop on bad selector
if(!matched){
throw 'Error parsing selector, parsing failed at "' + q + '"';
}
}
if(mm[1]){
fn[fn.length] = 'mode="'+mm[1].replace(trimRe, "")+'";';
q = q.replace(mm[1], "");
}
}
fn[fn.length] = "return nodup(n);\n}";
eval(fn.join(""));
return f;
}
[/code]
而compile方法会使用正则表达式匹配selector,然后分别去选择调用quickId/getNodes/byId/byTag/byClassName等特定查询模式的实现function
正则表达式匹配selector:
[code]
matchers : [{
re: /^\.([\w-]+)/,
select: 'n = byClassName(n, null, " {1} ");'
}, {
re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
select: 'n = byPseudo(n, "{1}", "{2}");'
},{
re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
}, {
re: /^#([\w-]+)/,
select: 'n = byId(n, null, "{1}");'
},{
re: /^@([\w-]+)/,
select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
}
]
[/code]
看看quickId/byId的实现:
[code]
function quickId(ns, mode, root, id){
if(ns == root){
var d = root.ownerDocument || root;
return d.getElementById(id);
}
ns = getNodes(ns, mode, "*");
return byId(ns, null, id);
}
function byId(cs, attr, id){
if(cs.tagName || cs == document){
cs = [cs];
}
if(!id){
return cs;
}
var r = [], ri = -1;
for(var i = 0,ci; ci = cs[i]; i++){
if(ci && ci.id == id){
r[++ri] = ci;
return r;
}
}
return r;
};
[/code]
如果是在默认的document下查找一个指定id的元素,则直接调用document.getElementById
否则用getNodes得到所有的子Dom元素,再用byId来匹配Id,第一个匹配上的返回

操作符匹配:
[code]
operators : {
"=" : function(a, v){
return a == v;
},
"!=" : function(a, v){
return a != v;
},
"^=" : function(a, v){
return a && a.substr(0, v.length) == v;
},
"$=" : function(a, v){
return a && a.substr(a.length-v.length) == v;
},
"*=" : function(a, v){
return a && a.indexOf(v) !== -1;
},
"%=" : function(a, v){
return (a % v) == 0;
},
"|=" : function(a, v){
return a && (a == v || a.substr(0, v.length+1) == v+'-');
},
"~=" : function(a, v){
return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
}
}
[/code]
pseudo class匹配:
[code]
first-child
last-child
nth-child
only-child
empty
contains
nodeValue
checked
not
any
odd
even
nth
first
last
has
next
prev
[/code]

http://www.niftyadmin.cn/n/727331.html

相关文章

不唐突的JavaScript的七条准则

经过多年的开发、教学和编写不唐突的JavaScript&#xff0c; 我发现了下面的一些准则。我希望它们可以帮助你对“为什么这样设计和执行JavaScript比较好”有一点理解。这些规则曾经帮助我更快地交付产品&#xff0c;并且产品的质量更高&#xff0c;也更容易维护。 1.不要做任何…

ftp服务器取文件怎么弄,3.3.4 获取FTP服务器文件信息(1)

3.3.4 获取FTP服务器文件信息(1)当用户编程时&#xff0c;需要获取FTP服务器文件的列表&#xff0c;以便查看文件的相关信息。在接下来的内容中&#xff0c;将讲解怎样获取FTP服务器文件的相关知识。(1) 获取文件列表一般情况下&#xff0c;FTP文件列表信息是通过客户端和服务…

你为什么不喜欢写周报

很多项目经理都讨厌写周报 1、不知道写什么。虽然每周有很多工作&#xff0c;但实际上却没有什么具体地&#xff0c;繁琐的事又不知道要不要写。 2、做了很多事&#xff0c;却不知道些什么。很多人明明做了很多事&#xff0c;但开始写的时候却不知道怎么写。 3、不喜欢写。有人…

为什么我要写博客

写博客是一个非常好的习惯&#xff0c;以前我没有意识到&#xff0c;还认为是在浪费时间&#xff0c;现在想起来真是错误的想法&#xff0c;后悔没有早点开始写博客。 现在不仅要写&#xff0c;而且还要强制自己去写。 写博客的优点很多&#xff0c;除了可以提高写作的水平和技…

响应服务器451,SMTP服务器响应:451

我已经构建了2个联系表单(quote.php和contact.php)&#xff0c;用jquery验证并提交给单独的ajax_contact.php和ajax_quote.php文件。它们都是基于我在其他网站上使用的相同模板构建的&#xff0c;但由于某种原因&#xff0c;ajax_contact.php返回此错误&#xff1a;Warning: ma…

TCP-IP详解笔记1.2 链路层

from [url]http://www.beyondrails.com/blogs/20[/url]注&#xff1a;这里的链路层应该是指网络接口层(Network Interface Layer)--TCP/IP协议族中的最底层&#xff0c;中文翻译时术语不同而已在TCP/IP协议族中&#xff0c;链路层主要有三个目的: 1)为IP模块发送和接受IP数据报…

10条Web可用性指南

10条Web可用性指南。 转自&#xff1a;http://blog.downke.cn/post/2009/10/07/10WebUseful.aspx1. Form标签最好放到字段的上面 UX Matters的一份研究发现表单中的标签(label)的理想位置是在字段(field)的上面。在很多的表单中&#xff0c;标签被放到字段的左边&#xff0c;以…

项目经理有这个能力,一开口就赢了

项目经理多数时间都是进行各种形式在沟通&#xff0c;其中难度最大的就是演讲。无论是团队之间的会议&#xff0c;还是向领导、客户汇报工作&#xff0c;都少不了必要的当面宣讲、表达。 对项目经理来说&#xff0c;演讲是不可避免的工作内容&#xff0c;因此掌握演讲的技巧确…