Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 05.09.2016, 18:49
Аспирант
Отправить личное сообщение для moron Посмотреть профиль Найти все сообщения от moron
 
Регистрация: 29.07.2012
Сообщений: 49

Изменение 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 методы?

Последний раз редактировалось moron, 05.09.2016 в 18:54.
Ответить с цитированием
  #2 (permalink)  
Старый 05.09.2016, 19:14
Профессор
Отправить личное сообщение для laimas Посмотреть профиль Найти все сообщения от laimas
 
Регистрация: 14.01.2015
Сообщений: 12,989

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");


Иначе в цикле на добавленные не сослаться.
Ответить с цитированием
  #3 (permalink)  
Старый 05.09.2016, 19:18
Аспирант
Отправить личное сообщение для moron Посмотреть профиль Найти все сообщения от moron
 
Регистрация: 29.07.2012
Сообщений: 49

Суть не совсем в этом.
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");
Ответить с цитированием
  #4 (permalink)  
Старый 05.09.2016, 19:21
Аспирант
Отправить личное сообщение для moron Посмотреть профиль Найти все сообщения от moron
 
Регистрация: 29.07.2012
Сообщений: 49

Баг как раз был в том что после innerHTML переставали работать методы к $a, потому что он указывал на уже удаленные узлы. А удаленны они были, потому что $root.get(0).innerHTML += "html"(развернувшись в $root.get(0).innerHTML = $root.get(0).innerHTML + "html") взял и перезаписал ВСЁ содержимое, что было. В том числе и $a, которые были получены раньше.
Ответить с цитированием
  #5 (permalink)  
Старый 05.09.2016, 19:25
Аспирант
Отправить личное сообщение для moron Посмотреть профиль Найти все сообщения от moron
 
Регистрация: 29.07.2012
Сообщений: 49

Вот небольшой пример. Посмотри на комментарий в 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 будет указывать на уже удаленные узлы..
Ответить с цитированием
  #6 (permalink)  
Старый 05.09.2016, 19:28
Профессор
Отправить личное сообщение для laimas Посмотреть профиль Найти все сообщения от laimas
 
Регистрация: 14.01.2015
Сообщений: 12,989

<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, вот тут могут быть неожиданности.
Ответить с цитированием
  #7 (permalink)  
Старый 05.09.2016, 19:32
Аспирант
Отправить личное сообщение для moron Посмотреть профиль Найти все сообщения от moron
 
Регистрация: 29.07.2012
Сообщений: 49

Длина будет правильной и даже содержимое коллекций будет верным, но на самом деле это будут лишь уже несуществующие дубликаты из dom, которые находятся лишь в памяти. Т.е любая манипуляция с $a не будет работать как ожидается(возможно изменения будут применяться к элементам, которых в dom в действительно уже НЕТ).
Просто модицифкация дом не даст такого поведения. Потому что не удалит все и не запишет заново, а лишь сделает частичные изменеия :с
Ответить с цитированием
  #8 (permalink)  
Старый 05.09.2016, 19:33
Аспирант
Отправить личное сообщение для moron Посмотреть профиль Найти все сообщения от moron
 
Регистрация: 29.07.2012
Сообщений: 49

т.е ты прав, что они будут доступным, но какой в этом смысл, если их нет в дом на самом деле?
Ответить с цитированием
  #9 (permalink)  
Старый 05.09.2016, 19:35
Профессор
Отправить личное сообщение для laimas Посмотреть профиль Найти все сообщения от laimas
 
Регистрация: 14.01.2015
Сообщений: 12,989

Сообщение от moron
но какой в этом смысл, если их нет в дом на самом деле?
Что значит нет? Консоль по примеру покажет
3, 4
3, 5

пятый что "бог подарил" или все такие есть в DOM?

PS. Видимо вопрос касается некоторых тонкостей присущих innerHTML, и речь об этом. Тогда здесь почитать.

Последний раз редактировалось laimas, 05.09.2016 в 19:39.
Ответить с цитированием
  #10 (permalink)  
Старый 05.09.2016, 19:38
Аспирант
Отправить личное сообщение для moron Посмотреть профиль Найти все сообщения от moron
 
Регистрация: 29.07.2012
Сообщений: 49

.b пятый есть и .b четвертый, а вот a. нет в дом вообще после innerHTML.
Иначе как ты обьяснишь, что после innerHTML пропадает родитель у .a?
console.log($a.eq(0).parent().prop("tagName"))

Последний раз редактировалось moron, 05.09.2016 в 19:42.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Изменение состояния DOM denysdovhan Events/DOM/Window 10 27.05.2014 12:54
Изменение масштаба в браузере с помощью js Bond Общие вопросы Javascript 3 09.04.2014 18:25
Повесить событие на изменение DOM nebaz Events/DOM/Window 5 17.06.2012 15:15
Изменение картинки с помощью radio magahed Элементы интерфейса 1 15.11.2011 20:59
Изменение параметра "ALT"("TITLE") тега IMG посредством DOM Гость Элементы интерфейса 3 21.02.2008 10:02