为querySelector
和querySelectorAll
document
和Element
的跨浏览器别名的最佳不显眼替代方案是什么?
最直接的方式可能是
window.$ = function(selector){return document.querySelector(selector)}
window.$$ = function(selector){return document.querySelectorAll(selector)}
当然这不允许链接,因为函数返回总是引用document
$('.parent-class').$$('.child-classes')
到目前为止,我最好的选择是
window.$ = document.querySelector.bind(document);
window.$$ = document.querySelectorAll.bind(document);
Element.prototype.$ = Element.prototype.querySelector;
Element.prototype.$$ = Element.prototype.querySelectorAll;
这样我们就可以做以前失败的选择器了,虽然我不确定这可能带来的不良影响,是否有人有提示/解释可以提供?
有没有人有一个很好的不引人注目的选择?
答案 0 :(得分:5)
我还使用bind
方法创建别名。
var $ = document.querySelector.bind(document);
var $$ = document.querySelectorAll.bind(document);
对于元素一,我使用一个函数和apply
,这样它的行为就像你称之为" VanillaJS"方式。
Element.prototype.$ = function() {
return this.querySelector.apply(this, arguments);
};
Element.prototype.$$ = function() {
return this.querySelectorAll.apply(this, arguments);
};
以下是一个例子:
var $ = document.querySelector.bind(document);
var $$ = document.querySelectorAll.bind(document);
Element.prototype.$ = function() {
return this.querySelector.apply(this, arguments);
};
Element.prototype.$$ = function() {
return this.querySelectorAll.apply(this, arguments);
};
alert($('.foo').innerHTML);
alert('There are ' + $$('.foo').length + ' `.foo` nodes');
var parent = $('.parent');
alert(parent.$('.child').innerText);
alert('There are ' + parent.$$('.child').length + ' children');

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<div class=foo>It works!</div>
<div class=foo>It worked again!</div>
<div class=parent>Parent
<div class=child>Child</div>
<div class=child>Another Child</div>
</div>
</body>
</html>
&#13;
如果你想要链接,你必须创造一些更精细的东西。您可能需要查看Bliss以获得支持链接的轻量级(~3kb)库,但更像是VanillaJS而不是jQuery。
答案 1 :(得分:4)
不引人注目的替代
制作一个包装器,这样你就不会扩展其他/本机结构,称之为不太可能发生冲突的东西
var Σ = (function () {
function Found(nodes) {
this.nodes = nodes;
}
function find(selector) {
var nodes;
if (this instanceof Found) {
nodes = Array.prototype.map.call(this.nodes, e => Array.prototype.slice.call(e.querySelectorAll(selector)));
nodes = Array.prototype.concat.apply([], nodes);
return new Found(nodes);
}
if (this === window)
return new Found(Array.prototype.slice.call(document.querySelectorAll(selector)));
return new Found(Array.prototype.slice.call(this.querySelectorAll(selector)));
}
Found.prototype.find = find;
return find;
}());
所以你可以做类似
的事情Σ('.answer').find('pre').nodes;
在此处获取答案中的所有<pre>
个节点(代码位)。您可以根据需要链接.find
。
跨浏览器
jQuery 有什么问题?
答案 2 :(得分:3)
最好的不引人注目的替代方案是不做这样的别名。这是另一件需要记住的事情,对于那些查看代码的人来说,这是另一回事,它可能会破坏IDE的自动完成和语法检查功能,并且会污染原型。
但是,如果你想沿着这条路走下去,它会采用特殊的机制来连接$$
和Element.$$
的任何东西,因为它们会返回节点列表。首先,我们将$$
返回一个数组:
window.$$ = function(sel) {
return Array.prototype.slice.call(document.querySelector(sel));
}
Element.$$
也一样。现在我们可以扩充Array
原型:
Array.prototype.$ = function(sel) {
var result = [];
for (var i = 0; i < this.length; i++) {
var sub = this[i].querySelector(sel);
if (sub) result.push(sub);
}
return result;
};
如果适合您的想法,请使用map
和/或filter
等重写此内容。
现在你可以做到:
$$('.class1').$('span')
同样,您可以在$$
上定义Array
的版本,如下所示:
Array.prototype.$$ = function(sel) {
var result = [];
for (var i = 0; i < this.length; i++) {
var elts = this[i].querySelectorAll(sel);
for (var j = 0; j < elts.length; j++) {
result.push(elts[j]);
}
}
return result;
;
它将输入节点列表中每个成员的querySelectorAll
调用产生的所有节点列表组合成一个单独的数组。
如果您希望链接setAttribute
之类的内容,则需要为Element
和Array
定义版本:
Element.prototype.setAttributeChainable = function() {
this.setAttribute.apply(this, arguments);
return this;
}
Array.prototype.setAttributeChainable = function() {
for (var i = 0; i < this.length; i++) {
this[i].setAttribute.apply(this[i], arguments);
}
return this;
}
要在$
什么都没找到时让它无声地失败,请安排它在这种情况下返回一个空数组:
window.$ = function(sel) {
return document.querySelector(sel) || [];
};
和Element.$
相同。
现在你可以做到
$$('.class1') .
$$('span') .
setAttributeChainable('style', 'color:blue') .
$('a') .
setAttributeChainable('href', 'google.com');
现在继续本练习,使用您想要链接和/或适用于节点列表的任何其他API。
如果您对添加Array
原型有宗教异议,那么您必须找到其他方法。