Предположим, что у меня есть элемент с id #msg
и при определенном условии я хочу добавить к нему класс, чтобы применить стиль, например. чтобы текст выглядел красным.
Я могу сделать $('#msg').addClass(theclass)
Мой вопрос: как реагирует браузер? Развертывает ли он всю страницу или повторно отображает этот конкретный элемент?
Изменяет ли браузер всю страницу на изменения или только конкретные элементы?
Ответ 1
В вашем примере (addClass
) это зависит от того, что находится в добавляемом вами классе. Добавление самого класса только изменяет атрибут на целевом node.
- Некоторые изменения вызовут repaint, то есть при изменении цвета, bgcolor и т.д. Только те элементы, к которым применяется новый CSS, будут повторно отображены.
- Некоторые изменения вызовут reflow, то есть когда пространство видимое, занятое элементами или их содержимым, изменит размеры или позицию. В зависимости от их собственных свойств и свойств родительских и дочерних объектов, а также свойств родительских и дочерних элементов и т.д. И т.д. Перепланирование будет влиять на большее количество элементов в дереве документов.
Браузеры достаточно умны, чтобы изменять только элементы, требующие повторной рендеринга. Метод минимизации количества повторных рендерингов состоит в том, чтобы установить элемент position: absolute
или display: none
, чтобы временно удалить его из потока документов, внести изменения, а затем снова вставить. Это особенно важно, если, например, вы делаете какой-то элемент скольжения вниз. Если элемент находится в потоке и в начале дерева DOM, каждый пиксель, который он растягивает, вызовет повторную визуализацию.
Ради удовольствия, сделайте простую аналогию с бумагой на столе, в этом примере с вставкой элементов. Стол - это окно вашего браузера, □
= бумага, _
= пустое пространство. Вы хотите поставить другой лист в верхнем левом положении. Это начальная ситуация:
□ □ □ □
□ □ □ □
_ _ _ _
После того, как вы положите новый лист на стол: (■ = новый, ▧ = перемещен)
■ □ □ □
▧ □ □ □
▧ _ _ _
Если вторая строка была одним длинным рулоном бумаги (= полный div), вся строка будет двигаться:
■ □ □ □
▧ _ _ _
▧▧▧▧▧▧▧
Если вы вставили лист в третью строку, переполнение не произойдет.
Примечание: Это теоретическое объяснение. Его эффективность будет зависеть от браузера. Источник: Высокопроизводительный Javascript, "Перепроверяет и переплачивает", стр .70.
Ответ 2
Мое понимание, основанное на результатах, представленных этим инструментом https://developer.chrome.com/devtools/docs/timeline, состоит в том, что НЕТ, весь DOM не перерисовывается/регенерируется, просто элемент, который имел изменение класса.
HTML:
<p>Lorem ipsum dolar sit amet...</p>
<input id="btn" type="button" value="click me" />
JavaScript:
$(document).on('click', '#btn', function () {
$('p').addClass('red')
})
CSS
.red {
color: red;
}
**** **** редактировать Мне пришлось изменить свой ответ от "Нет" к "Да", а затем "Нет" от "Да". Этот инструмент четко указывает на перерисовку рассматриваемого элемента, другие элементы DOM не затрагиваются.
Однако Если внутренний/внешний размер элемента изменяется или даже нужно запрашивать javascript, для этого потребуется перерисовать элемент DOM, и вся ветвь элементов будет перерисована, а затем кэширована браузером.