ExtJs源码分析与学习—ExtJs元素Element(五)

元素的查询Ext.DomQuery

 

    该类结合css选择器可以提供高效的查询。首先说一下DOM中对文档元素的查询,主要有以下方法

  •     document.getElementById(id)
  •     element.getElementsByTagName(tagName)

    DOM对应的6个属性来获取其父、子及兄弟节点的引用

  •     parentNode 指向其父节点的引用
  •     previousSibling 指向前一个兄弟节点的引用
  •     nextSibling 指向后一个兄弟节点的引用
  •     firstChild 指向其第一个节点的引用
  •     lastChild 指向其最后一个节点的引用
  •     childNodes 返回所有子节点的引用的集合


     下面看该类中几个主要方法。先看combination过滤器的实现,共有四种模式,分别为EF,E/F(E>F),E+F,E~F,格模式详见程序中的注释和实现。

 

Js代码    收藏代码
  1.         /** 
  2.      * 实现combination选择器的查询方式 
  3.      * @param {} ns 要查询的元素或元素集合 
  4.      * @param {} mode 查询模式 
  5.      * @param {} tagName 标签名 
  6.      */  
  7. function getNodes(ns, mode, tagName){  
  8.         var result = [], ri = -1, cs;  
  9.         if(!ns){  
  10.             return result;  
  11.         }  
  12.         tagName = tagName || "*";//没有指定tagName,默认为所有的元素,注意这里用*来查询所有  
  13.         //ns参数值为element时,先封装成数组,后续统一处理  
  14.         if(typeof ns.getElementsByTagName != "undefined"){  
  15.             ns = [ns];  
  16.         }  
  17.         if(!mode){//后代选择器,符号值为 " " E F模式,查询E标签下所有标签名为F的后代元素  
  18.             for(var i = 0, ni; ni = ns[i]; i++){//找到结果集中所有满足的元素  
  19.                 cs = ni.getElementsByTagName(tagName);  
  20.                 for(var j = 0, ci; ci = cs[j]; j++){//找到所有满足tagName的后代元素  
  21.                     result[++ri] = ci;  
  22.                 }  
  23.             }  
  24.         } else if(mode == "/" || mode == ">"){// E/F 或E>F 模式,查询E标签下所有标签名为F的子元素,只有一层,而EF模式为所有后代元素,会有好几层的查询  
  25.             var utag = tagName.toUpperCase();  
  26.             for(var i = 0, ni, cn; ni = ns[i]; i++){  
  27.                 cn = ni.childNodes;  
  28.                 for(var j = 0, cj; cj = cn[j]; j++){  
  29.                     if(cj.nodeName == utag || cj.nodeName == tagName  || tagName == '*'){  
  30.                         result[++ri] = cj;  
  31.                     }  
  32.                 }  
  33.             }  
  34.         }else if(mode == "+"){// E+F模式,在E标签下的所有元素集合中,查找每个元素的相邻的后续兄弟元素(只找第一个后续兄弟)中标签为F的元素  
  35.             var utag = tagName.toUpperCase();  
  36.             for(var i = 0, n; n = ns[i]; i++){  
  37.                 while((n = n.nextSibling) && n.nodeType != 1);  
  38.                 if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){  
  39.                     result[++ri] = n;  
  40.                 }  
  41.             }  
  42.         }else if(mode == "~"){// E~F模式,在E标签下的所有元素集合中,查找每个元素的相邻的后续兄弟元素中标签为F的元素  
  43.             var utag = tagName.toUpperCase();  
  44.             for(var i = 0, n; n = ns[i]; i++){  
  45.                 while((n = n.nextSibling)){  
  46.                     if (n.nodeName == utag || n.nodeName == tagName || tagName == '*'){  
  47.                         result[++ri] = n;  
  48.                     }  
  49.                 }  
  50.             }  
  51.         }  
  52.         return result;  
  53.     }  

 

      接下来看过滤器的实现。Ext.DomQuery中提供了5中过滤方式:id、class、tagName、attribute、pseudo(伪操作根据函数),为此也相应的提供了byId、byClassName、byTag、byAttribute、byPseudo 5个函数来实现,下面主要看byAttribute

 

Js代码    收藏代码
  1.       /** 
  2.  
  3. * @param {} cs 要查询的元素结合 
  4. * @param {} attr 属性名 
  5. * @param {} value 属性对应的值 
  6. * @param {} op 操作符 
  7. * @param {} custom 对于元素属性,采用[],对于css样式则采用{} 
  8. */  
  9.   function byAttribute(cs, attr, value, op, custom){  
  10.       var result = [],   
  11.           ri = -1,   
  12.           useGetStyle = custom == "{",        
  13.           fn = Ext.DomQuery.operators[op],//DOM操作符      
  14.           a,//根据判断的属性来取得元素对应的属性值或css样式属性值  
  15.           xml,  
  16.           hasXml;  
  17.             
  18.       for(var i = 0, ci; ci = cs[i]; i++){  
  19.    // skip non-element nodes.  
  20.           if(ci.nodeType != 1){//忽略不是元素节点  
  21.               continue;  
  22.           }  
  23.           // only need to do this for the first node  
  24.           if(!hasXml){  
  25.               xml = Ext.DomQuery.isXml(ci);  
  26.               hasXml = true;  
  27.           }  
  28.      
  29.           // we only need to change the property names if we're dealing with html nodes, not XML  
  30.           // html节点的处理  
  31.           if(!xml){  
  32.               if(useGetStyle){  
  33.                   a = Ext.DomQuery.getStyle(ci, attr);  
  34.               } else if (attr == "class" || attr == "className"){  
  35.                   a = ci.className;  
  36.               } else if (attr == "for"){  
  37.                   a = ci.htmlFor;  
  38.               } else if (attr == "href"){  
  39.     // getAttribute href bug  
  40.     // http://www.glennjones.net/Post/809/getAttributehrefbug.htm  
  41.                   a = ci.getAttribute("href", 2);  
  42.               } else{  
  43.                   a = ci.getAttribute(attr);  
  44.               }  
  45.           }else{  
  46.               a = ci.getAttribute(attr);  
  47.           }  
  48.           if((fn && fn(a, value)) || (!fn && a)){  
  49.               result[++ri] = ci;  
  50.           }  
  51.       }  
  52.       return result;  
  53.   }  

 

    下面看select方法:选择一组元素

 

Js代码    收藏代码
  1.            select : document.querySelectorAll ? function(path, root, type) {  
  2.     root = root || document;  
  3.     if (!Ext.DomQuery.isXml(root)) {  
  4.         try {  
  5.             var cs = root.querySelectorAll(path);  
  6.             return Ext.toArray(cs);  
  7.         } catch (ex) {  
  8.         }  
  9.     }  
  10.     return Ext.DomQuery.jsSelect.call(this, path, root, type);  
  11. } : function(path, root, type) {  
  12.     return Ext.DomQuery.jsSelect.call(this, path, root, type);  
  13. },  

 

      该函数分为两种情况,如果支持document.querySelectorAll,优先调用该方法返回。调用传入的参数path为选择器,root为开始查询的节点,默认为document。该方法的别名为"Ext.query = Ext.DomQuery.select;"。另外该类也是单例模式,代码实现比较复杂,内部用到了缓存机制,代码中有三个缓存变量

 

Js代码    收藏代码
  1. var cache = {},   
  2.         simpleCache = {},   
  3.     valueCache = {},  
  • cache缓存了选择器的编译(compile)结果
  • simpleCache缓存了选择器的简单(simple)编译结果
  • valueCache 缓存了选择器查询元素的值
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值