首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网站开发 > JavaScript >

[Js++开发过程] 巧妙使用querySelector实现类似JQuery.is函数

2014-01-05 
[Js++开发历程] 巧妙使用querySelector实现类似JQuery.is函数var tagTokenRe /^(#)?([\w\\-\\*]+)/func

[Js++开发历程] 巧妙使用querySelector实现类似JQuery.is函数
var tagTokenRe = /^(#)?([\w\\-\\*]+)/;function is(dom, selector) { var tokenMatch = selector.match(tagTokenRe); if (tokenMatch) { if (tokenMatch[1] == "#") { if (dom.id != tokenMatch[2]) { return false; } } else { if (dom.tagName.toLowerCase() != tokenMatch[2].toLowerCase()) { return false; } } selector = selector.replace(tokenMatch[0], ""); if (!selector) return true; } var pdom; if (dom && (pdom = dom['parentNode'])) { var id = dom.id; if (!id) { dom.id = id = "_J" + ++$.guid; } selector = '#' + id + selector; var ret = pdom.querySelector(selector); return ret !== null; } return false;}

?以上缺点是要保障子dom的兄弟不能有相同的ID

?为了保障,可以将

?

var id = dom.id;        if (!id) {            dom.id = id = "_J" + ++$.guid;        }        selector = '#' + id + selector;        var ret = pdom.querySelector(selector);

改为第二种方案

?

var id = dom.id;       dom.id = '_JIS_'        selector = '#' + dom.id + selector;        var ret = pdom.querySelector(selector);dom.id = id?id:null;

这样就可以保证ID的唯一性,但会降低性能。

?

?

?

?

第三种方案,采用存JS实现的如下:

?

var modeRe = /^(\s?[\/>+~]\s?|\s|$)/,            tagTokenRe = /^(#)?([\w\\-\\*]+)/,            tplRe = /\{(\d+)\}/g,            cache = {};        var matchers = [            {re: /^\.([\w-]+)/, select: 'n = byClassName(n, " {1} ");if(n.length==0) return false;\n'},            {re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/, select: 'n = byPseudo(n, "{1}", "{2}");if(n.length==0)return false;\n'},            {re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/, select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");if(n.length==0) return false;\n'},            {re: /^#([\w-]+)/, select: 'n = byId(n, "{1}");if(n.length==0) return false;\n'}        ];        var 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;            }        };        var pseudos = {            "contains": function (c, v) {                var r = [], ri = -1;                for (var i = 0, ci; ci = c[i]; i++) {                    if ((ci.textContent || ci.innerText || '').indexOf(v) != -1) {                        r[++ri] = ci;                    }                }                return r;            },            "checked": function (c) {                var r = [], ri = -1;                for (var i = 0, ci; ci = c[i]; i++) {                    if (ci.checked == true) {                        r[++ri] = ci;                    }                }                return r;            }        };        function compile(path) {            // setup fn preamble            var fn = ["var f = function(root){\nvar n = root || document;\n"],                lastPath,                matchersLn = matchers.length,                modeMatch;            // strip leading slashes            while (path.substr(0, 1) == "/") {                path = path.substr(1);            }            while (path && lastPath != path) {                lastPath = path;                var tokenMatch = path.match(tagTokenRe);                if (tokenMatch) {                    if (tokenMatch[1] == "#") {                        fn[fn.length] = 'n = byId(n, "' + tokenMatch[2] + '");if(n.length==0) return false;\n';                    } else {                        fn[fn.length] = 'n = byTag(n, "' + tokenMatch[2] + '");if(n.length==0) return false;\n';                    }                    path = path.replace(tokenMatch[0], "");                }                while (!(modeMatch = path.match(modeRe))) {                    var matched = false;                    for (var j = 0; j < matchersLn; j++) {                        var t = matchers[j];                        var m = path.match(t.re);                        if (m) {                            fn[fn.length] = t.select.replace(tplRe, function (x, i) {                                return m[i];                            });                            path = path.replace(m[0], "");                            matched = true;                            break;                        }                    }                    // prevent infinite loop on bad selector                    if (!matched) {                        throw 'Error parsing selector, parsing failed at "' + path + '"';                    }                }            }            // close fn out            fn[fn.length] = "\nreturn n.length>0;\n}";            // eval fn and return it            eval(fn.join(""));            return f;        }        function byId(cs, id) {            if (cs.tagName || cs == document) {                cs = [cs];            }            if (!id) {                return cs;            }            var result = [], ri = -1;            for (var i = 0, ci; ci = cs[i]; i++) {                if (ci && ci.id == id) {                    result[++ri] = ci;                    return result;                }            }            return result;        }        function byTag(cs, tagName) {            if (cs.tagName || cs == document) {                cs = [cs];            }            if (!tagName) {                return cs;            }            var result = [];            tagName = tagName.toLowerCase();            for (var i = 0, ci; ci = cs[i]; i++) {                if (ci.nodeType == 1 && ci.tagName.toLowerCase() == tagName) {                    result.push(ci);                }            }            return result;        }        function byAttribute(cs, attr, value, op, custom) {            var result = [],                ri = -1,                fn = operators[op],                a,                innerHTML;            for (var i = 0, ci; ci = cs[i]; i++) {                // skip non-element nodes.                if (ci.nodeType != 1) {                    continue;                }                innerHTML = ci.innerHTML;                // we only need to change the property names if we're dealing with html nodes, not XML                if (innerHTML !== null && innerHTML !== undefined) {                    if (attr == "class" || attr == "className") {                        a = ci.className;                    } else if (attr == "for") {                        a = ci.htmlFor;                    } else if (attr == "href") {                        a = ci.getAttribute("href", 2);                    } else {                        a = ci.getAttribute(attr);                    }                } else {                    a = ci.getAttribute(attr);                }                if ((fn && fn(a, value)) || (!fn && a)) {                    result[++ri] = ci;                }            }            return result;        }        function byClassName(nodeSet, cls) {            if (!cls) {                return nodeSet;            }            var result = [], ri = -1;            for (var i = 0, ci; ci = nodeSet[i]; i++) {                if ((' ' + ci.className + ' ').indexOf(cls) != -1) {                    result[++ri] = ci;                }            }            return result;        }        function byPseudo(cs, name, value) {            if (cs.tagName || cs == document) {                cs = [cs];            }            return pseudos[name](cs, value);        }

经过1000000的测试:

第一种方案需要9849ms,第二种方案需要13124ms,第三种方法需要9729ms。

?

?

?

?

热点排行