我正在编写一个用户脚本,它提取与指定CSS选择器匹配的所有链接,然后在这些链接的子节点之间执行多次搜索,然后更改找到的元素的属性。我正在寻找一种方法,不是每次搜索前都匹配第一个选择器的所有链接,而只是一次。 示例HTML:
<div>
<a class="some_class" href="http://some_href"><b>Link1</b></a>
<a class="another_class" href="http://another_href"><b>Link2</b></a>
<a class="some_class" href="http://www.some_href">Link3</a>
</div>
<span>
<a class="some_class" href="some_href"><b>Link4</b></a>
</span>
使用Javascript:
var links=document.querySelectorAll('a.some_class');
//some actions with the hrefs
//the following code could be a solution, but doesn't work as I need.
//it tries to get b elements from the extracted links with matching href
//but generally this selector depends on some calculations with links
links.querySelectorAll('a[href$="some_href"] b')[0].style.display='none';
//NodeLists don't have this method
//another way:
//trying to create document fragment from NodeList to call method on it
var fragment=document.createDocumentFragment();
for(var i=0; i<links.length; i++){
fragment.appendChild(links[i]);
//Link is removed from page, so this also is not suitable
}
当然,我可以简单地遍历NodeList的所有chidlren,但是如果有很多链接和很多搜索,它就太慢了。
答案 0 :(得分:1)
您正在谈论的是过滤列表。
首先你得到清单:
var links=document.querySelectorAll('a.some_class');
然后你想要过滤它,例如只找到那些也匹配a[href$="some_href"] b
的那些(但据我所知,这取决于所讨论的链接)。
我可能首先将NodeList作为一个数组:
links = Array.prototype.slice.call(links, 0);
...所以我可以使用各种漂亮的Array方法。
然后:
var bElementsUnderSomeHref = [];
var someOtherCriterion = [];
links.forEach(function(link) {
var b;
if (link.href.substr(-9) === "some_href") {
b = link.querySelector("b");
if (b) {
bElementsUnderSomeHref.push(b);
}
}
if (/*...some other criterion...*/) {
someOtherCriterion.push(/*...something relevant...*/);
}
});
我正在进行单个循环,但如果出于任何原因需要,可以使用单独的循环。单个循环可以节省一些执行时间,但这并不是很慢。正如I demonstrated last time您试图提出这个问题,即使是IE8也可以循环(比方说)20,000个元素,并对每个元素进行嵌套querySelector
/ querySelectorAll
调用很短暂的时间。对我来说,旧的XP VM中的IE8在320ms内完成。 Chrome可以在60岁以下。
答案 1 :(得分:0)
老实说,我喜欢你使用文档片段的方法,但可以稍微修改一下。也就是说,您需要使用具有深度选项的节点克隆,并且使用原型也不会很糟糕。不确定它的效率如何,但看起来真的非常漂亮。
来源:http://jsfiddle.net/FLXRx/
演示:http://jsfiddle.net/FLXRx/show/(结果显示在控制台中)
NodeList.prototype.querySelectorAll = function(selector){
var fragment=document.createDocumentFragment();
for(var i=0; i<this.length; i++){
fragment.appendChild(this[i].cloneNode(true));
}
return fragment.querySelectorAll(selector);
}
var links=document.querySelectorAll('a.some_class');
console.log(links.querySelectorAll('a[href$="some_href"] b'));