javascript - 前端如何写出高效选择器?
巴扎黑
巴扎黑 2017-04-10 14:37:25
0
4
327

css也好jq也好?
怎么样的选择器是高效的?

巴扎黑
巴扎黑

membalas semua(4)
巴扎黑

首先,我要说没必要来实现选择器这种轮子,虽然我不反对造轮子,但选择器这种轮子已经非常成熟了,而且现代浏览器已经内置了选择器。

不过如果你坚持还是要继续的话,我可以简单探讨下。顺便说一下,jquery的选择器用的是sizzle,它以前用的是自己写的,不过后来大概也觉得这个轮子没啥意思。。。

第一步,解析

首先要把你的查询字符串解析成查询链,这个过程简单但是繁杂,因为除了常见的css选择器,还有各种伪类。我们就拿最简单的一个查询来举例子把,我把我们的选择器叫做X

X('#header .nav ul');

这段代码经过我们的解析后会变成类似这样的结构

[
    {type: 'id', value: 'header'},
    {type: 'class', value: 'nav'},
    {type: 'tag', value: 'ul'}
]

OK,这样一个简单的查询链就出来了,理论上我们按照这个顺序一步一步就可以得到期望的结果了。

第二步,查询

注意,如果你没有用querySelector这个函数,那么基本上就是利用 getElementById, getElementsByName, getElementsByTagName, getElementsByClassName 这几个函数来实现了

我们可以把上面查询链的type给映射到具体的操作,类似

var handlers = {
    'id' : function (el, value) {
        return el.getElementById(value);
    },
    ...
};

最后,我们遍历这条查询链,根据每个节点的type来查询value,然后把每个节点结果作为下一个查询的el,依此类推

注意,以上只是做一个选择器的基本原理,实际情况要复杂的多

小葫芦

把jQuery的抄一遍是极好的 ( ͡° ͜ʖ ͡°)

黄舟

这篇文章很好的回答了你的问题,推荐:

Efficiently Rendering CSS

PHPzhong

以前不知道瀏覽器有 querySelector,所以自己寫了一個,不過功能不全。
額外的好處是修改一下也可以用來創建元素(類似 Emmet)。
效率肯定不如瀏覽器自帶的。


function $(x) { var s = (function(t) { var s = { tagName: "", id: "", classes: [], attributes: [] }, p = [], i, j; var m = { "]" : "[" }, n = false; for (i = t.length - 1, j = t[i]; i >= 0; j = t[--i]) { if (!n) { switch (j) { case ".": s.classes.push(p.join("")); p = []; break; case "#": s.id = p.join(""); p = []; break; case "]": n = true; p = []; break; default: p.unshift(j); } } else { switch (j) { case "[": s.attributes.push(p.join("")); p = []; n = false; break; default: p.unshift(j); } } } s.tagName = (p.join("")); //alert(s.tagName + ", #" + s.id + ", ." + s.classes.join(", .")); return s; }(x)); var y = []; if (s.id) y = [document .getElementById(s.id)] .filter(function(v) { if (s.tagName) return v.tagName === s.tagName.toUpperCase(); return true; }); else if (s.tagName) y = (Array.prototype.slice.call(document .getElementsByTagName(s.tagName))); else if (s.classes.length > 0 || s.attributes.length > 0) if (!y || !y.length > 0) y = Array.prototype.slice.call(document .getElementsByTagName('*')); if (s.classes.length > 0) y = y.filter(function(v) { var c = v.className.split(" "); return s.classes.every(function(n) { return c.indexOf(n) !== -1; }); }); if (s.attributes.length > 0) y = y.filter(function(v) { return s.attributes.every(function(n) { n = n.split("="); var attributeName = n[0].trim(); if (v.hasAttribute(attributeName)) if (n.length === 1) return true; else { return v.getAttribute(attributeName) === n[1].trim().replace(/^"|"$/g, ''); } return false; }); }); return y; }
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan