Выберите теги, которые начинаются с "x-" в jQuery
Как я могу выбрать узлы, которые начинаются с "x-"
имя тега, вот пример иерархического дерева DOM:
<div>
<x-tab>
<div></div>
<div>
<x-map></x-map>
</div>
</x-tab>
</div>
<x-footer></x-footer>
JQuery не позволяет мне запрашивать $('x-*')
Есть ли способ, которым я мог бы достичь этого?
9 ответов
Нет никакого собственного способа сделать это, у него худшая производительность, так что просто сделайте это сами.
Пример:
var results = $("div").find("*").filter(function(){
return /^x\-/i.test(this.nodeName);
});
Полный пример:
Примечания: (Обновлено, см. Комментарии)
Если вам интересно, почему я использую этот способ для проверки имени тега, см.:
JavaScript: поиск без учета регистра
и увидеть комментарии.
Кроме того, если вам интересно find
метод вместо добавления к селектору, поскольку селекторы сопоставляются справа, а не слева, может быть лучше отделить селектор. Я также мог бы сделать это:$("*", $("div"))
, Желательно, хотя вместо того, чтобы просто div
добавить идентификатор или что-то к нему, чтобы родительское совпадение было быстрым.
В комментариях вы найдете доказательство того, что это не быстрее. Я полагаю, что это относится к очень простым документам, где стоимость создания объекта jQuery выше, чем стоимость поиска всех элементов DOM. В реалистичных размерах страниц, хотя это не будет иметь место.
Обновить:
Мне также очень нравится ответ Тейфи. Вы можете сделать это в одном месте, а затем использовать его везде. Например, позвольте мне смешать мой путь с его:
// 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 <a> 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.
Ниже просто работает нормально. Хотя я не уверен в производительности, так как использую регулярные выражения.
$('body *').filter(function(){
return /^x-/i.test(this.nodeName);
}).each(function(){
console.log(this.nodeName);
});
PS: в приведенном выше примере, я рассматриваю body
пометить как родительский элемент.
ОБНОВЛЕНИЕ:
После проверки сообщения Мохамеда Мелиги кажется, что регулярное выражение быстрее, чем манипулирование строками в этом состоянии. и это может стать более быстрым (или таким же), если мы используем find
, Что-то вроде этого:
$('body').find('*').filter(function(){
return /^x-/i.test(this.nodeName);
}).each(function(){
console.log(this.nodeName);
});
ОБНОВЛЕНИЕ 2:
Если вы хотите искать в документе, то вы можете сделать ниже, что является самым быстрым:
$(Array.prototype.slice.call(document.all)).filter(function () {
return /^x-/i.test(this.nodeName);
}).each(function(){
console.log(this.nodeName);
});
Это может быть неэффективно, но рассмотрите это как последний вариант, если вы не получили никакого ответа.
Попробуйте добавить пользовательский атрибут к этим тегам. Я имею в виду, когда вы добавляете тег, например, для. <x-tag>
Добавьте пользовательский атрибут с ним и присвойте ему то же значение, что и тег, чтобы HTML выглядел следующим образом <x-tag CustAttr="x-tag">
,
Теперь, чтобы получить теги, начинающиеся с x-
, вы можете использовать следующий код jQuery:
$("[CustAttr^=x-]")
и вы получите все теги, которые начинаются с x-
Пользовательский селектор jquery
jQuery(function($) {
$.extend($.expr[':'], {
X : function(e) {
return /^x-/i.test(e.tagName);
}
});
});
чем использовать $(":X")
или же $("*:X")
выбрать ваши узлы.
Хотя это не дает прямого ответа на вопрос, оно может дать решение, "определив" теги в селекторе, вы можете получить все эти типы?
$('x-tab, x-map, x-footer')
Обходной путь: если вы хотите эту вещь более одного раза, возможно, будет гораздо эффективнее добавить класс, основанный на теге, что вы делаете в начале только один раз, а затем отфильтруете для тега тривиальный способ.
Я имею в виду,
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);
});
}
После этого вы можете сделать $("[class^='tag- x-']") или то же самое с querySelectorAll, и это будет достаточно быстро.
Посмотрите, работает ли это!
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;
}
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');
}
}
Попробуй это
var test = $('[x-]');
if(test)
alert('eureka!');
В основном селектор jQuery работает как селектор CSS. Прочитайте API выбора jQuery здесь.