Использование jQuery для поиска строки HTML

Если я запустил этот код -

var html= '<html><head></head><body><div class="bar"></div></body></html>';
console.log($(html).find('div'));

Я не получаю никаких результатов, если я запустил этот код -

var html= '<html><head></head><body><div><div class="bar"></div></div></body></html>';
console.log($(html).find('div'));

Затем я получаю единственный результат - внутренний div (<div class="bar"></div>). Я ожидал, что первый фрагмент кода вернет один результат, а второй фрагмент - два результата.

Точно так же этот код не возвращает результатов -

var code = $("<div id='foo'>1</div><div id='bar'>2</div>");
console.log(code.find('div'));

но этот код дважды предупреждает 'div' -

var code = $("<div id='foo'>1</div><div id='bar'>2</div>");
code.each(function() {
    alert( this.nodeName );
})

Учитывая результат второго фрагмента, я ожидал, что первый фрагмент кода вернет два результата. Может кто-нибудь объяснить, почему я получаю те результаты, которые получаю?

http://jsfiddle.net/ipr101/GTCuv/


person ipr101    schedule 23.08.2011    source источник
comment
Я изменил console.log на alert, и он предупредил [object Object], значит, он что-то нашел ...   -  person Eran Zimmerman Gonen    schedule 23.08.2011
comment
@ Эран Циммерман: Это потому, что jQuery всегда возвращает объект, независимо от количества совпадений, найденных для селектора.   -  person Björn    schedule 23.08.2011
comment
Я предполагаю, что [объект Object] относится к пустому массиву, который возвращает jQuery.   -  person ipr101    schedule 23.08.2011


Ответы (4)


Разобьем этот вопрос на две части.

Первый:

var html= '<html><head></head><body><div class="bar"></div></body></html>';
console.log($(html).find('div'));

а также

var html= '<html><head></head><body><div><div class="bar"></div></div></body></html>';
console.log($(html).find('div'));

не работают, потому что согласно jQuery() docs:

При передаче сложного HTML некоторые браузеры могут не создавать модель DOM, которая точно копирует предоставленный источник HTML. Как уже упоминалось, мы используем свойство браузера .innerHTML для анализа переданного HTML и вставки его в текущий документ. Во время этого процесса некоторые браузеры отфильтровывают определенные элементы, такие как элементы <html>, <title> или <head>. В результате вставленные элементы могут не соответствовать исходной переданной строке.

  • В первом блоке кода ваши теги <html>, <head> и <body> удаляются, а <div class="bar"></div> остается. find выполняет поиск только внутри полученного <div> и ничего не может найти.
  • Во втором блоке кода ваши теги <html>, <head> и <body> удаляются, а <div><div class="bar"></div></div> остается. find ищет внутри результата и находит единственный <div>.

Что касается вашей второй части:

var code = $("<div id='foo'>1</div><div id='bar'>2</div>");
console.log(code.find('div'));

Сначала вы даете jQuery строку, которую он принимает и превращает в объект jQuery с двумя <div>. Затем find ищет в каждом <div>, ничего не находит и не возвращает результатов.

Далее в

var code = $("<div id='foo'>1</div><div id='bar'>2</div>");
code.each(function() {
    alert( this.nodeName );
})

each перебирает объект jQuery, беря каждый из двух созданных <div>, и предупреждает имя их узла. Таким образом, вы получаете два предупреждения.

person Digital Plane    schedule 23.08.2011

Ответ очень простой. когда вы создаете объект с помощью jQuery (html), тогда он создает иерархию узлов, и когда вы находите какой-либо узел, такой как 'div', он выполняет поиск по всей иерархии, кроме корневых элементов, и в вашем первом примере у вас нет дочернего 'div' узлы. И во втором примере у вас есть только один дочерний узел 'div'.

поэтому, если вы сохраните один дополнительный корневой узел во всей иерархии, вы легко сможете найти все свои узлы. нравиться

var html= '<html><head></head><body><div class="bar"></div></body></html>';
console.log($('<div></div>').append(html).find('div'));

var html= '<html><head></head><body><div><div class="bar"></div></div></body></html>';
console.log($('<div></div>').append(html).find('div'));
person vicky    schedule 23.08.2011
comment
вот как это должно быть сделано. Принятый ответ не будет работать, если корневых элементов больше 1. - person ProblemsOfSumit; 09.02.2015
comment
Это правильный ответ. Альтернативный вариант письма, который подходит мне, - это $('<div>'+html+'</div>').find('div') - person rAthus; 03.06.2021

Простой способ выглядит следующим образом:

Учитывая строку:

var html= '<html><head></head><body><div class="bar"></div></body></html>';

Найдите div с помощью панели классов:

$(html).filter('.bar')

Или все div:

$(html).filter('div')

Возвращает объект с классом bar

person Jeff    schedule 12.01.2017
comment
большой! ты спасешь мой день! - person Darlan D.; 31.01.2018
comment
У меня это работает. - person Jonjie; 26.06.2021

.find в третьем примере выполняет поиск дочерних элементов в каждом совпадающем элементе. Внутри ваших divs нет div дочерних элементов (у них нет детей), поэтому .find(anything) не вернет никаких элементов.

.each, с другой стороны, выполняет итерацию по текущим элементам в наборе, который включает divs ( есть два совпадающих элемента - divs).

Что касается <html> в вашем первом примере, я не уверен - возможно, вам не разрешено создавать второй элемент <html> после загрузки страницы. $('<html><head></head><body><div class="bar"></div></body></html>'); возвращает только div, поэтому .find ничего не возвращает.

person pimvdb    schedule 23.08.2011
comment
jQuery (или, точнее, браузер) удаляет теги html, head и body и сохраняет только содержимое body. - person Felix Kling; 23.08.2011