Изменение DOM с помощью innerHTML
Здраствуйте.
Получилось, что из-за собственных пробелах в знаниях я долго бился с неочевидным(возможно лишь для меня) поведением. Опытным путем мне удалось найти источник проблемы. Проблема была в добавлении элементов дом с помощью innerHTML: после добавление таким способом к полученным ранее элементам с помощью jQuery не работали методы insertAfter или просто after(возможно не работало вообще все. Вплоть до изменение стилей). Я сделал небольшое демо и 2 вариации. Есть контенер с двумя типами элеметов(.b и .a). В .a примешиваются элементы .b с некоторым шансом. Перед самим примешиванием я добавляю еще один .b элемент(разными спобами) и в варианте с innerHTML потом не могу работать с ранее полученными элементами. Если вставка через append(понятно, что метод append jquery вызывает нативный Node.appendChild), то он не генерит новый дом, а лишь действительно вставляет новый элемент[исходник jq](поэтому старые элементы все еще куда-то указывают), в то время как elem.innerHTMl += "html_text" разворачивается в elem.innerHTML = elem.innerHTML + "html_text" и весь дом у нас получается новый, плюс происходит, что старые ноды никуда не деваются, ведь на них все еще указывается jquery like обьект(и потенциально мы выхватываем лишнию память, для уже несуществующих узлов - да?)... Итак, демо: 1) Вариант с innerHTML 2) Вариант с append Какая помощь мне нужна: Какой литературой я могу восполнить свои знания и в каких еще случаях я могу столкнуться с такими проблемами? Есть ли в моих размышлениях какие-то ошибки? Я наслышан, что прямые методы работы с dom занимают больше времени, чем простой innerHTML, но что если у нас вставки в dom происходят достаточно часто и относительно большими пачками(штук 20), при этом к тому моменту уже могут находиться ~100элементов и перерисовывать их нежелательно из-за усложенения анимации :с Может ли быть такое, что использовать innerHTML на каком-то этапе станет менее оптимально, нежели вставка через dom методы? |
var $a = $(".a"), $b = $("#root").append("<div class='b'>b-dynamic</div>").find('.b'); //и var $a = $(".a"); $("#root").get(0).innerHTML += "<div class='b'>b-dynamic</div>"; var $b = $("div.b"); Иначе в цикле на добавленные не сослаться. |
Суть не совсем в этом.
1) мы получаем $a 2) добавляем в $root.get(0).innerHTML += "строка с большим количеством .b" 3) теперь $a так же недоступен. Т.е второй вариант, тобой предложенный так же не сможет работать с .a после innerHTML var $a = $(".a"); $("#root").get(0).innerHTML += "<div class='b'>b-dynamic</div>"; var $b = $("div.b"); |
Баг как раз был в том что после innerHTML переставали работать методы к $a, потому что он указывал на уже удаленные узлы. А удаленны они были, потому что $root.get(0).innerHTML += "html"(развернувшись в $root.get(0).innerHTML = $root.get(0).innerHTML + "html") взял и перезаписал ВСЁ содержимое, что было. В том числе и $a, которые были получены раньше.
|
Вот небольшой пример. Посмотри на комментарий в js
http://codepen.io/mogafk/pen/qaEVVV т.е пример var $a = $(".a"); $("#root").get(0).innerHTML += "<div class='b'>b-dynamic</div>"; var $b = $("div.b"); Так же имеет баг, потому что $a будет указывать на уже удаленные узлы.. |
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <style> </style> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script> <script> $(function() { var $a = $(".a"), $b = $("#root").append("<div class='b'>b-dynamic</div>").find('.b'); console.log($a.length, $b.length) $("#root").get(0).innerHTML += "<div class='b'>b-dynamic</div>"; var $b = $("div.b"); console.log($a.length, $b.length) }); </script> </head> <body> <div id="root"> <div class="a">a</div> <div class="a">a</div> <div class="a">a</div> <hr /> <div class="b">b</div> <div class="b">b</div> <div class="b">b</div> </div> </body> </html> Хоть как добавлять, доступными они будут. А вот то что вы получили коллекцию, с которой хотите работать, а затем модифицировали DOM, вот тут могут быть неожиданности. |
Длина будет правильной и даже содержимое коллекций будет верным, но на самом деле это будут лишь уже несуществующие дубликаты из dom, которые находятся лишь в памяти. Т.е любая манипуляция с $a не будет работать как ожидается(возможно изменения будут применяться к элементам, которых в dom в действительно уже НЕТ).
Просто модицифкация дом не даст такого поведения. Потому что не удалит все и не запишет заново, а лишь сделает частичные изменеия :с |
т.е ты прав, что они будут доступным, но какой в этом смысл, если их нет в дом на самом деле?
|
Цитата:
3, 4 3, 5 пятый что "бог подарил" или все такие есть в DOM? PS. Видимо вопрос касается некоторых тонкостей присущих innerHTML, и речь об этом. Тогда здесь почитать. |
.b пятый есть и .b четвертый, а вот a. нет в дом вообще после innerHTML.
Иначе как ты обьяснишь, что после innerHTML пропадает родитель у .a? console.log($a.eq(0).parent().prop("tagName")) |
Часовой пояс GMT +3, время: 11:35. |