extjs css selector 分析-1

css selector dom 实现的常见步鄹: (from Secrets of the JavaScript Ninja)

1.解析 selector 字串

如根据 \s+ 将 "div span a" 分解为 [div,span,a]

2.获取元素

如上例,先由 getElementsByTagName 得到所有的 div ,再在 div 数组中得到 所有的后代 span

3.过滤元素

由于 div 可能有后代 div ,所以 按照 2 步得到的 span 集合 ,会有重复元素,需要unique 操作,去除重复的span

4.递归与合并

  上述每步我们只处理一个标签,得到结果,那么剩下标签的处理则可以递归处理,得到的结果则要与递归前的结果合并。


根据上述步鄹直觉写出的例子:

function find(selector, root){
    root = root || document;

    //解析
    var parts = selector.split(""),
    query = parts[0],
    rest = parts.slice(1).join(""),

    //获取元素
    elems = root.getElementsByTagName( query ),
    results = [];
    for ( var i = 0; i < elems.length; i++ ) {
        if ( rest ) {

        //合并,注意还要过滤
        results = results.concat(

        //递归
         find(rest, elems[i]) );
        } else {
        results.push( elems[i] );
        }
    }
    return results;
}
 






上述程序有几个问题:

1.同一个selector多次使用,没有任何效率提升,即没有使用缓存机制
2.递归处理效率不高,每次合并+过滤非常耗费时间

 

 

DomQuery :

extjs 对于 selector 的处理十分巧妙,不是简单的 online分析 selector 字串,对于以上问题有自己的解决之道,
类似于 Ext.template ,Extjs 非常创意的将 css selector编译为一系列 的dom 操作调用所组成的动态生成函数,如:

alert(Ext.DomQuery.compile("div span a"));


//解析 selector 字串在编译期已经做了
//递归也不需要,直接生成调用序列
function (root) {
 var mode;
 ++batch;
 var n = root || document;
 //获取元素
 n = getNodes(n, mode, "div");
 mode = "";
 n = getNodes(n,mode, "span");
 mode = "";
 n = getNodes(n, mode, "a");

 //过滤元素
 return nodup(n);
}
 



可见 extjs 的处理方式 省去了
 
1.解析 selector 开销
2.递归开销
 
并且编译形成的函数可以和 selector 字串关联起来,可以缓存了.


现在关键就是 extjs 的 compile过程了,有空再说吧。

注:


1.w3c 有新标准 css selector ,querySelector 与 querySelectorAll  IE6,7 not supported


2.w3c以前的标准:xpath 语言与 css selector 不同,复杂难用,需要程序做中间层将 css selector
转换成对应的 xpath


3.Ext selector engine 原来叫 DomQuery ,出来时比当时的 jquery 快好多,ejohn 和 jack 有过一段争论,很有意思,有兴趣可以搜搜看



你可能感兴趣的:(JavaScript,jquery,css,REST,ext)