JQuery после того, как метод не работает с вновь созданными элементами
Насколько я могу судить, следующий код должен работать, создавая элемент <div>
, а затем создавая элемент <p>
; выражение должно приводить к созданию объекта jQuery с двумя элементами:
$("<div>first element content</div>").after("<p>second element content</p>");
Однако, я получаю совсем другое. Документация (см. заголовок "Вставка отключенных узлов DOM" ) сообщает мне, что приведенный выше код должен приводить к созданию объекта jQuery, захватывая как фрагменты HTML, так и строя два элемента DOM. Но, что я получил, в нескольких разных версиях jQuery, все выше 1.4, является объектом jQuery только с 1 node. Тем не менее, следующий код работает просто отлично, возвращая (я считаю,) правильный объект jQuery, два элемента внутри:
$("<div></div>").after("<p>second element content</p>");
И этот пример также работает:
$("<div></div>").after("<p>second element content</p>").after("<p>third element content</p>");
Кажется, что метод .after()
работает отлично, если созданный первый DOM node пуст, но не тогда, когда он отсутствует (независимо от содержимого последующих узлов DOM, присоединенных к нему).
Мне что-то не хватает о внутренних функциях jQuery, причудливых проблемах DOM и/или особенностях JavaScript, или это просто ошибка jQuery, которая сохранялась с версии 1.4 на 1.7?
(Вот скудный JSFiddle, демонстрирующий проблему довольно ясно.)
Ответы
Ответ 1
Это была известная ошибка в jQuery < 1,9. См. http://bugs.jquery.com/ticket/8759
В jQuery >= 1.9 следует отметить следующую информацию из руководства по обновлению:
До 1.9, .after()
, .before()
и .replaceWith()
будут пытаться добавлять или изменять узлы в текущем наборе jQuery, если первый node в наборе не был связан с документом, а в тех случаи возвращают новый набор jQuery, а не оригинальный набор. Это создало несколько несоответствий и неполадок - метод мог или не мог возвращать новый результат в зависимости от его аргументов! Начиная с 1.9, эти методы всегда возвращают исходный немодифицированный набор и пытаются использовать .after()
, .before()
или .replaceWith()
на node без родительского эффекта, т.е. Ни набор, ни узлы он содержит изменения.
Ответ 2
Используйте add()
для добавления объектов в коллекцию. Я использую after()
больше в элементах DOM, которые уже существуют или кэшируются в переменной, но большую часть времени, если вы работаете с динамической разметкой, более практично использовать эквивалентный insertAfter()
.
$("<div>first element content</div>").add("<p>second element content</p>");
EDIT:
Это работает...
var $el = $('<div/>', {
text: 'hey there'
}).after('<p>Lorem</p>');
Ответ 3
Я обнаружил, что у меня по-прежнему возникали проблемы с .add()
вместо .after()
, поэтому еще один простой способ обойти эту ошибку - сделать броский элемент-обертку, .append()
элементы-братья и использовать .html()
, чтобы просто получить внутреннее содержимое обертки.
Пример:
$('body').append(
$('<span/>').append(
$("<div>first element content</div>")
).append(
$("<p>second element content</p>")
).html()
);
Это добавит <div>
и <p>
, но отменит внешний <span>
. Я обнаружил, что обычно это нормально работает с .append()
, но может иметь проблемы с .appendTo()