Javascript-форум (https://javascript.ru/forum/)
-   Events/DOM/Window (https://javascript.ru/forum/events/)
-   -   Реализация DOM (https://javascript.ru/forum/events/49845-realizaciya-dom.html)

Alexander34 31.08.2014 09:10

Реализация DOM
 
Всем доброго дня!!! Пытаюсь глубже понять реализацию DOM в браузерах и недавно наткнулся на такой случай. Есть обычная страница:
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>анимация переходы</title>
<style>
div {
	width: 300px;
	height: 300px;
	background-color: red;
	opacity: 1;
	transition-property: all;
	transition-duration: 1s;
}

#d {
	width: 300px;
	height: 300px;
	background-color: blue;
	opacity: 0;
	transition-property: all;
	transition-duration: 1s;
}
</style>
</head>
<body>
<button id="btn">click</button>
<div></div>
<div id="d"></div>
<script>
 var div = document.getElementsByTagName("div")[0];
 var d = document.getElementById("d");
 document.body.removeChild(d);
 var button = document.getElementById("btn");
</script>
</body>
</html>


В стиле описан переход transition, элемент <div id="d"> сразу же удаляю из DOM(можно просто создать его и хранить в переменной). Если кликнуть по кнопке, то js изменить opacity элемента и мы видим плавный переход. Вот 2 реализации в js
1)
var div = document.getElementsByTagName("div")[0];
 var d = document.getElementById("d");
 document.body.removeChild(d);
 var button = document.getElementById("btn");
 button.onclick = function() {
 	div.style.opacity = 0;
 	setTimeout(function(){ 
 		document.body.appendChild(d);
 		d.style.opacity = 1;
 	},1000);
 }

В данной реализации, появление второго div-а , происходит резко(без перехода). Но если добавить таймаут, то переход будет плавный.
2)
var div = document.getElementsByTagName("div")[0];
 var d = document.getElementById("d");
 document.body.removeChild(d);
 var button = document.getElementById("btn");
 button.onclick = function() {
 	div.style.opacity = 0;
 	setTimeout(function(){ 
 		document.body.appendChild(d);
 		setTimeout(function() {
 			d.style.opacity = 1;
 		},100);
 	},1000);
 }


С чем это связано? Данная проблема возникает, если вставить в DOM элемент, а затем изменить style. Если же элемент есть в DOM, то все работает плавно. Проверено в IE11, chrome ff последних версий. Мастера js дайте подсказку и рекомендации. Спасибо!

vvkk 31.08.2014 20:46

Возможно какое то время тратится на отрисовку созданого динамически элемента. Т.е по факту в дереве DOM он уже присутвует но не отрисован самим броузером.Когда броузер его отобразит произойдет смещение по времени и мы увидим почти мгновенное отображение, но на самом деле плавное.Javascript да однопоточен, но когда он выполнит инструкцию document.body.appendChild(d); это не значит что отобразит его, а перейдет к следующей d.style.opacity = 1; И пройзойдет смещение. Скорее всего это можно отнести к багу.

ixth 31.08.2014 22:53

Да, действительно похоже на баг. Я тебе больше скажу, посмотри на мой вариант:

<button id="btn">smooth</button><br/>
<div></div>
<div id="d"></div>
<style>
div {
	display:inline-block;
	width: 100px; height: 100px;
	background-color: red;
	opacity: 1;
	transition-property: all;
	transition-duration: 1000ms;
}

#d {
	background-color: blue;
	opacity: 0;
}
</style>

<script>
var div = document.getElementsByTagName("div")[0];
var d = document.getElementById("d");
d.parentNode.removeChild(d);

document.getElementById("btn").onclick = function () {
 	div.style.opacity = 0;
 	setTimeout(function(){ 
 		document.body.appendChild(d);
*!*
 		console.log(d.offsetTop);
*/!*
 		d.style.opacity = 1;
 	}, 1000);
};
</script>


Видимо, это как-то связано с оптимизацией обращений к DOM. Есть там какая-то хитрота, не помню точно, отпишу, если найду.

Alexander34 02.09.2014 08:09

Спасибо! Буду дальше разбираться, буду ждать новых сообщений.


Часовой пояс GMT +3, время: 19:43.