关于javascript:在jQuery中选择以“x-”开头的标签

Select tags that starts with “x-” in jQuery

如何选择以"x-"标记名开头的节点,下面是一个层次结构dom树示例:

1
2
3
4
5
6
7
8
  <x-tab>
   
   
      <x-map></x-map>
   
  </x-tab>

<x-footer></x-footer>

jquery不允许我查询$('x-*'),我有什么方法可以做到这一点吗?


下面的工作很好。虽然我不确定性能,因为我正在使用regex。

1
2
3
4
5
$('body *').filter(function(){
    return /^x-/i.test(this.nodeName);
}).each(function(){
    console.log(this.nodeName);
});

工作小提琴

在上面的示例中,我考虑将body标记作为父元素。

更新:

在检查了MohamedMeligy的帖子之后,在这种情况下,regex似乎比字符串操作更快。如果我们使用find,它可能会更快(或相同)。像这样:

1
2
3
4
5
$('body').find('*').filter(function(){
    return /^x-/i.test(this.nodeName);
}).each(function(){
    console.log(this.nodeName);
});

杰斯普夫试验

更新2:

如果要在文档中搜索,则可以执行以下最快的操作:

1
2
3
4
5
$(Array.prototype.slice.call(document.all)).filter(function () {
    return /^x-/i.test(this.nodeName);
}).each(function(){
    console.log(this.nodeName);
});

杰斯普夫试验


没有本地的方法可以做到这一点,它的性能最差,所以,你自己动手吧。

例子:

1
2
3
var results = $("div").find("*").filter(function(){
    return /^x\-/i.test(this.nodeName);
});

完整例子:

http://jsfiddle.net/6B8YY/3/

注:(更新,见评论)

如果您想知道我为什么用这种方式检查标记名,请参见:javascript:不区分大小写的搜索也可以看到评论。

另外,如果您想知道使用find方法而不是添加到选择器,因为选择器是从右而不是从左匹配的,所以最好将选择器分离。我也可以这样做:$("*", $("div"))。最好是添加一个ID或其他内容,而不是只添加div,这样父匹配就很快了。

在评论中,你会发现一个证据,证明这并不快。这适用于非常简单的文档,尽管我相信,在这些文档中,创建jquery对象的成本高于搜索所有DOM元素的成本。但在实际的页面大小中,情况并非如此。

更新:

我也很喜欢泰菲的回答。你可以在一个地方完成它,然后在任何地方重用它。例如,让我把我的方式和他的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// In some shared libraries location:
$.extend($.expr[':'], {
    x : function(e) {
            return /^x\-/i.test(this.nodeName);
    }
});

// Then you can use it like:
$(function(){
    // One way
    var results = $("div").find(":x");

    // But even nicer, you can mix with other selectors
    //    Say you want to get  tags directly inside x-* tags inside <section>
    var anchors = $("section :x > a");

    // Another example to show the power, say using a class name with it:
    var highlightedResults = $(":x.highlight");
    // Note I made the CSS class right most to be matched first for speed
});

这是同样的性能冲击,但更方便的API。


自定义jquery选择器

1
2
3
4
5
6
7
jQuery(function($) {
    $.extend($.expr[':'], {
        X : function(e) {
            return /^x-/i.test(e.tagName);
        }
    });
});

然后,使用$(":X")$("*:X")选择节点。


它可能不高效,但如果你没有得到任何答案,就把它当作最后的选择。尝试向这些标记添加自定义属性。我的意思是,当您为添加一个标记时,用它添加一个自定义属性,并赋予它与标记相同的值,这样HTML看起来就像一样。现在,要获取从x-开始的标记,可以使用以下jquery代码:

1
$("[CustAttr^=x-]")

你会得到所有以x-开头的标签。


虽然这不能直接回答问题,但它可以提供一个解决方案,通过在选择器中"定义"标记,您可以获得所有类型的标记?

1
$('x-tab, x-map, x-footer')


解决方法:如果你不止一次想要这个东西,那么基于标签添加一个类可能会更有效率——你一开始只做一次,然后用简单的方法过滤标签。

我的意思是

1
2
3
4
5
6
7
8
9
10
11
12
function addTagMarks() {
    // call when the document is ready, or when you have new tags

    var prefix ="tag--"; // choose a prefix that avoids collision
    var newbies = $("*").not("[class^='"+prefix+"']"); // skip what's done already

    newbies.each(function() {
        var tagName = $(this).prop("tagName").toLowerCase();
        $(this).addClass(prefix + tagName);
    });

}

在此之后,您可以对querySelectorAll执行$("[class^='tag--x-'])或相同的操作,它将相当快。


演示小提琴

1
2
3
4
5
6
var i=0;
for(i=0; i< document.all.length; i++){
    if(document.all[i].nodeName.toLowerCase().indexOf('x-') !== -1){
        $(document.all[i].nodeName.toLowerCase()).addClass('test');
    }
}

看看这是否有效!

1
2
3
4
5
6
7
8
9
10
function getXNodes() {
  var regex = /x-/, i = 0, totalnodes = [];
  while (i !== document.all.length) {
    if (regex.test(document.all[i].nodeName)) {
      totalnodes.push(document.all[i]);
    }
    i++;
  }
  return totalnodes;
}

试试这个

1
2
3
var test = $('[x-]');
if(test)
    alert('eureka!');

基本上jquery选择器的工作方式与css选择器类似。在这里阅读jquery选择器API。