【问题标题】:Using querySelectorAll to get ALL elements with that class name, not only the first使用 querySelectorAll 获取具有该类名的所有元素,而不仅仅是第一个
【发布时间】:2015-03-21 18:16:10
【问题描述】:

我在大约 9(ish) 个月前放弃了 jquery,需要一个选择器引擎(没有所有麻烦,也不介意 ie

// "qsa" stands for: "querySelectorAll"
window.qsa = function (el) {
  var result = document.querySelectorAll(el)[0];
  return result;
};

这在 95% 的情况下都可以正常工作,但我已经有一段时间遇到这个问题了,我研究过 mdn、w3c、SO,不要忘记 Google :) 但还没有找到原因的答案我只得到请求类的第一个元素。 而且我知道只有返回的第一个元素是由末尾的“[0]”引起的,但是如果我删除它,该函数将不起作用,所以我尝试使用增加的索引变量创建一个 for 循环值取决于具有该类的元素的长度,如下所示:

window.qsa = function (el) {
  var result, el = document.querySelectorAll(el);
  for(var i = 0; i < el.length; ++i) {
   result = el[i];
  }
  return result;
};

还是不行,所以我尝试了这样的 while 循环:

window.qsa = function (el) {
  var result, i = 0, el = document.querySelectorAll(el);
  while(i < el.length) {
    i++;
  }
  result = el[i];
  return result;
};

现在我开始怀疑是否有什么有效的方法?我对 document.querySelectorAll 感到非常沮丧...... 但是我顽固的内心一直在前进,我一直在失败(分层循环),所以我知道现在真的是时候问这些问题了:

为什么只返回该类的第一个元素而不是全部?

为什么我的 for 循环会失败?

为什么我的 while 循环会失败?

感谢您,因为我们非常感谢您提供任何/所有帮助。

【问题讨论】:

  • 它是如何使用的?
  • 为什么不只使用return document.querySelectorAll(el)?
  • 问题肯定出在你使用它的地方。删除 [0] 将返回元素的 NodeList 而不是单个元素,因此您只需在访问元素时将其视为数组即可。

标签: javascript selectors-api


【解决方案1】:

为什么它只返回该类的第一个元素而不是全部?

因为您明确地从结果中获取第一个元素并返回它。

为什么我的 for 循环失败了?

因为每次循环结束时都会用新值覆盖result。然后你返回你得到的最后一个东西。

为什么我的 while 循环会失败?

同样的原因。


如果你想要所有元素,那么你只需要运行函数的结果:

return document.querySelectorAll(el)

这将为您提供一个包含所有元素的 NodeList 对象。


现在你说你想要的,我要推测你真正的问题是什么(即为什么你认为它不起作用)。

你没有向我们展示你对运行该函数的结果做了什么,但我猜你是想把它当作一个元素来对待。

它不是一个元素。它是一个NodeList,就像一个数组。

例如,如果您想更改元素的背景颜色,您可以这样做:

element.style.backgroundColor = "red";

如果你想改变 NodeList 中每个元素的背景颜色,那么你必须依次改变每个元素的背景颜色:使用循环。

for (var i = 0; i < node_list.length; i++) {
    var element = node_list[i];
    element.style.backgroundColor = "red";
}

【讨论】:

  • 或 window.qsa = document.querySelectorAll.bind(document); 但我猜 OP 想做qsa('p .something').classList.add('my-class')
  • 感谢您对我的深入了解。
【解决方案2】:

您正在返回单个元素。您可以返回数组。如果您希望能够一次作用于所有元素,jQuery 风格,您可以将回调传递给您的函数;

window.qsa = function(query, callback) {
    var els = document.querySelectorAll(query);
    if (typeof callback == 'function') {
        for (var i = 0; i < els.length; ++i) {
            callback.call(els[i], els[i], i);
        }
    }
    return els;
};


qsa('button.change-all', function(btn) {
    // You can reference the element using the first parameter
    btn.addEventListener('click', function(){
        qsa('p', function(p, index){
            // Or you can reference the element using `this`
            this.innerHTML = 'Changed ' + index;
        });
    });
});

qsa('button.change-second', function(btn) {
    btn.addEventListener('click', function(){
        var second = qsa('p')[1];
        second.innerHTML = 'Changed just the second one';
    });
});
<p>One</p>
<p>Two</p>
<p>Three</p>

<button class='change-all'>Change Paragraphs</button>
<button class='change-second'>Change Second Paragraph</button>

然后你可以调用任何使用回调

qsa('P', function(){
    this.innerHTML = 'test';
});

或者你可以使用返回的数组

var pList = qsa('p');
var p1 = pList[0];

【讨论】:

  • 非常感谢你这么棒的遮阳篷工作得很好,为我节省了很多文件大小,代码风格也很棒,如果可以的话,我会投票一百万次 :-)
【解决方案3】:

这个循环

for(var i = 0; i < el.length; ++i) {
 result = el[i];
}

每次都会覆盖您的结果变量。这就是为什么你总是只得到一个元素。

您可以在外部使用结果,并对其进行迭代。有点像

var result = window.qsa(el)
for(var i = 0; i < result.length; ++i) {
  var workOn = result[i];
  // Do something with workOn
}

【讨论】:

  • 我会有一百万次,但我还没有 15 个代表点,所以很遗憾我还不能投票。
  • 继续努力 :-)
猜你喜欢
  • 1970-01-01
  • 2014-04-24
  • 2015-08-08
  • 2016-07-31
  • 2012-10-08
  • 1970-01-01
  • 2022-12-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多