• QWrap Selector之W3C版


    之前也曾经有过一系列《QWrap Selector解密》 文章,讲到过QWrap里的dom/selector.js里的大多数要点。今天又整了一个完全依赖浏览器的querySelectorAll的slector版本:selector_w3c.js。与之前的selector.js的接口名称相同。

    我们自己写一个selector.js,这样我们就有弥补标准的不足的自由。例如,就算最新的浏览器,也依然没有人严格实现matchesSelector。而我们的selector.js里早就有了filter与test方法来实现matchesSelector的功能。
    从另一个角度看,我们有时需要为某些特定场景定制一些代码,以些来节约网络流量。selector_w3c.js就是假设浏览器已支持querySelectorAll方法。典型的例子就是:基于移动终端做的web js开发。
    selector_w3c.js与selector.js对外提供的所有方法名称都一样,只是有w3c版里对参数的要求与对应的处理,更依赖于浏览器。
    例如:

    1. 差别1:原来的selector.js中的Selector.query(document.body,'body div')不会反回结果。因为它为了易用性的考虑,把后面的selector字符串默认加上了“:scope ”,相当于selector_w3c.js里的Selector.query(document.body,':scope body div'),尽管现在Chrome也没有实现:scope伪类。这种差别在这篇《认识selector写法》  的文章中也讲过,是一个严谨性易用性冲突的典型例子。
    2. 差别2:seletor_w3c.js里的test方法里的selector参数现在也支持各种关系符了。例如,可以这样写:Selector.test(document.body,'html body')。同时它也产生了一个副作用,即:如果被测试的元素没有父元素(例如新建的、还未插入到dom树里去的节点),则测试结果为假。
    3. 差别3:seletor_w3c.js里的filter(els, sSelector, pEl)在未传pEl时,会忽略游离在dom树之外的节点。

    很可惜,因为chrome也没有实现matchesSelector,所以test、filter两个方法我只能去山寨的去实现一下,所以有了上面的差别2与差别3里的瑕玼。----这说明,“标准”总走跑不赢我们的期望,现实的浏览器又跑不赢标准。----管他呢,反正那“标准”是“草案”还是“建议”还是其他的什么,都不是我能左右的。

    代码具体代码在这里: https://github.com/wedteam/qwrap/blob/master/resource/js/dom/selector_w3c.js
    其实很简单,如下:

    /*
    Copyright (c) Baidu Youa Wed QWrap
    version: $version$ $release$ released
    author: JK
    */


    /**
    * @class Selector Css Selector相关的几个方法
    * @singleton
    * @namespace QW
    */
    (function() {
    var Selector = {
    /**
    * 把一个selector字符串转化成一个过滤函数.
    * @method selector2Filter
    * @static
    * @param {string} sSelector 过滤selector
    * @returns {function} : 返回过滤函数。
    * @example:
    var fun=selector2Filter("input.aaa");alert(fun);
    */
    selector2Filter: function(sSelector) {
    return s2f(sSelector);
    },
    /**
    * 判断一个元素是否符合某selector.
    * @method test
    * @static
    * @param {HTMLElement} el: 被考察参数
    * @param {string} sSelector: 过滤selector
    * @returns {function} : 返回过滤函数。
    */
    test: function(el, sSelector) {
    return s2f(sSelector)(el);
    },
    /**
    * 用一个css selector来过滤一个数组.
    * @method filter
    * @static
    * @param {Array|Collection} els: 元素数组
    * @param {string} sSelector: 过滤selector。
    * @param {Element} pEl: 父节点。默认是document
    * @returns {Array} : 返回满足过滤条件的元素组成的数组。
    */
    filter: function(els, sSelector, pEl) {
    var allEls = (pEl || document).querySelectorAll(sSelector);
    return Array.filter(els, function(el){
    return Array.indexOf(allEls,el) > -1;
    });
    },
    /**
    * 以refEl为参考,得到符合过滤条件的HTML Elements. refEl可以是element或者是document
    * @method query
    * @static
    * @param {HTMLElement} refEl: 参考对象
    * @param {string} sSelector: 过滤selector,
    * @returns {array} : 返回elements数组。
    * @example:
    var els=query(document,"li input.aaa");
    for(var i=0;i<els.length;i++ )els[i].style.backgroundColor='red';
    */
    query: function(refEl, sSelector) {
    return toArray((refEl || document).querySelectorAll(sSelector));
    },
    /**
    * 以refEl为参考,得到符合过滤条件的一个元素. refEl可以是element或者是document
    * @method one
    * @static
    * @param {HTMLElement} refEl: 参考对象
    * @param {string} sSelector: 过滤selector,
    * @returns {HTMLElement} : 返回element,如果获取不到,则反回null。
    * @example:
    var els=query(document,"li input.aaa");
    for(var i=0;i<els.length;i++ )els[i].style.backgroundColor='red';
    */
    one: function(refEl, sSelector) {
    return (refEl || document).querySelector(sSelector);
    }
    };


    /*
    * s2f(sSelector): 由一个selector得到一个过滤函数filter
    */
    var filterCache = {};
    filterCache[''] = function(){
    return true;
    };
    filterCache['*'] = function(el){
    return !!el.tagName;
    };
    function s2f(sSelector) {
    if (!filterCache[sSelector]) {
    filterCache[sSelector] = function (el) {
    return el.parentNode && Array.indexOf(el.parentNode.querySelectorAll(sSelector), el) > -1;
    }

    }
    return filterCache[sSelector];
    }
    function toArray(arr){
    for (var i=arr.length-1, ret = []; i>-1; i--) {
    ret[i] = arr[i];
    }
    return ret;
    }
    QW.Selector = Selector;
    }());


    另:由于QWrap有灵活的apps机制,所以我们可以订制一个apps/qwrap_webkit.js的应用,用selector_w3c.js来取代selector.js。而其他地方的代码不用任何改变。

    附:
    QWrap博客网址:http://www.qwrap.com
    Selector速度比赛:http://dev.qwrap.com/resource/js/_tools/speedmatch/_examples/SelectorSpeed.html

  • 相关阅读:
    使用MailKit发送邮件
    移动APP设备锁功能开发中的问题
    Xamarin.Form指纹认证
    Android App安装启动时签名校验
    网络编程学习资料
    ASP.NET Core 2.1发布/部署到Ubuntu并配置Nginx反向代理实现ip访问
    @media用法解释
    CSS calc() 函数
    css3属性box-sizing:border-box 用法解析
    浮动塌陷-overflow:hidden来解决
  • 原文地址:https://www.cnblogs.com/jkisjk/p/qwrap_selector_w3c.html
Copyright © 2020-2023  润新知