querySelector和querySelectorAll别名

时间:2015-12-08 13:37:50

标签: javascript dom alias

querySelectorquerySelectorAll

执行documentElement的跨浏览器别名的最佳不显眼替代方案是什么?

最直接的方式可能是

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;

这样我们就可以做以前失败的选择器了,虽然我不确定这可能带来的不良影响,是否有人有提示/解释可以提供?

有没有人有一个很好的不引人注目的选择?

3 个答案:

答案 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;
&#13;
&#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之类的内容,则需要为ElementArray定义版本:

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原型有宗教异议,那么您必须找到其他方法。