2013-11-06 2 views
4

У меня есть несколько сот «строки» элементы, как это:избежать HTML документа перекомпоновки

<div class='row'> 
    <div class='cell'></div> 
    <div class='cell'></div> 
    <div class='cell'></div> 
</div> 

Мне нужно, чтобы получить их clientHeight после того, как они были предоставлены на странице уже. Я знаю, что свойство «clientHeight» заставляет плавать, и это убивает мою работу, так как их так много. Однако - они уже отображаются, и я знаю, что их размер не меняется между временем их рендеринга и временем, которое я запрашиваю для их высоты.

Есть ли способ сказать браузеру НЕ перепланировать при запросе на высоту? Более того - WebKit инспектор говорит:

Layout tree size 5901 
Layout scope  Whole document 

И дивы находятся в абсолютно позиционированном предке - не только абсолютно позиционирован элемент будет переформатирование?

Edit:

Так ответы, являются правильными. Я был на самом деле засыпывая макет, потому что у меня был этот цикл:

rows.each(function(){ 
    $(this).css('height', this.clientHeight); 
}); 

Изменение кода к этому Устранена проблема:

var heights = rows.map(function(){ 
    return this.clientHeight; 
}); 
rows.each(function(){ 
    $(this).css('height', heights.shift()); 
}); 
+0

Одно предложение. Если вы можете сделать свою строку div статичной в начале и получить innerHieght, а затем изменить ее на абсолютную. Или добавляя и удаляя класс, вы можете рассчитать общую сумму ваших узлов. – Khamidulla

+0

Почему вы используете div для моделирования таблицы вместо использования таблицы? –

ответ

6

Свойство clientHeight не заставляет оплакивать, по крайней мере, не само по себе. Вам нужно две вещи, чтобы вызвать оплавление:

  1. грязного текущую раскладку (установить свойство макета, как ширина или высота)
  2. запроса свойство макета (clientHeight например)

Вы можете легко пакетные вызовы, чтобы установить ширину или высоту, и переключение не произойдет, пока контекст JS не освободит управление.Вы можете легко выполнять пакетные запросы для свойств макета, и обновление не произойдет, если текущий макет не загрязнен.

Проблема возникает, если вы делаете 1 и 2 подряд. Переплавление принудительно, чтобы удовлетворить ваш запрос с точной информацией.

Насколько я знаю, вы правы, что наличие абсолютно позиционированного предка должно ограничивать оплату от «распространения» по всему документу (родитель абсолютно позиционированного предка не будет переплавлять). Все предметы внутри абсолютно позиционированного предка по-прежнему будут оплачены!

Что касается решения вашей проблемы, есть. Установить механизм кэширования, как это (псевдокод):

forEachDiv(function(div) { 
    div.getClientHeight = function(){ 
    return div.cachedClientHeight = div.cachedClientHeight || div.clientHeight; 
    } 
}); 

Вы можете использовать div.getClientHeight() вместо div.clientHeight столько раз, сколько вы хотите, и только первое использование вызовет оплавления (если загрязнен).

Очевидно, что, соблюдая первое предложение, вы также можете искусственно запрашивать clientHeight для всех div в одной партии (= один возврат), и после этого у вас больше нет проблем.

// cache the client height for all divs now, to avoid reflows later 
forEachDiv(function(div) { 
    div.getClientHeight(); 
}); 
+0

Это правильно. Спасибо. В моем цикле я делал: element.style.height = element.clientHeight. Если я сначала забираю все высоты, а затем устанавливаю их в другом цикле, ненужных перерасчетов нет. – disc0dancer

+0

Что такое 'div.getClientHeight()'? Вы имели в виду 'div.getBoundingClientRect()'? –

+0

@AlejandroIglesias Это настраиваемая функция, которая кэширует высоту, чтобы избежать принудительных перекосов. – Tibos

20

оплавления в очередь при изменении DOM, но только выполняется, когда:

  1. Там больше нет Javascript для процесса (конец сценария) или

  2. Когда вы запрашиваете расчетное значение, которое должно быть отображено, например clientHeight.

Таким образом, чтобы избежать перекомпоновки, вы должны соблюдать следующие правила

  • Не запрашивать DOM, а вы его изменения и

  • Не изменять DOM если вы хотите получить к нему запрос

На практике это означает, что вы должны сгруппировать все свои операции запроса на конец скрипта после того, как вы сделали это с модификацией DOM. Выполнение этого будет выполняться только один раз для тысяч элементов вместо тысяч раз для каждого элемента.

+0

Хороший ответ проголосовали. Можете ли вы предоставить пример javascript? Для новичков, пожалуйста. – Khamidulla

Смежные вопросы