Изменение 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, время: 08:46. |