Pertanyaan Menghindari rilisan dokumen HTML


Saya memiliki beberapa ratus "baris" elemen seperti ini:

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

Saya harus mendapatkan klien mereka setelah mereka telah diberikan di halaman. Saya tahu bahwa properti "clientHeight" memaksa pengulangan dan ini membunuh kinerja saya karena ada begitu banyak dari mereka. Namun - mereka sudah diberikan dan saya tahu bahwa ukuran mereka tidak berubah antara waktu yang diberikan dan waktu yang saya minta untuk ketinggian mereka.

Apakah ada cara untuk memberi tahu browser agar TIDAK mengalir saat menanyakan ketinggian? Selain itu - inspektur webkit mengatakan:

Layout tree size  5901
Layout scope      Whole document

Dan div berada dalam leluhur yang benar-benar diposisikan - seharusnya tidak hanya elemen yang benar-benar terposisikan yang direfleksikan?

Edit:

Jadi jawaban yang diberikan sudah benar. Saya sebenarnya mengotori tata letak karena saya memiliki lingkaran ini:

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

Mengubah kode untuk memperbaiki masalah ini:

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

4
2017-11-06 15:16


asal


Jawaban:


Properti clientHeight tidak memaksakan reflow, setidaknya tidak dengan sendirinya. Anda memerlukan dua hal untuk memicu pengulangan:

  1. kotor tata letak saat ini (atur properti tata letak seperti lebar atau tinggi)
  2. query properti tata letak (clientHeight misalnya)

Anda dapat dengan mudah mengirim panggilan untuk mengatur lebar atau tinggi dan tidak ada pengulangan akan terjadi sampai konteks JS melepaskan kontrol. Anda dapat dengan mudah mengurutkan kueri untuk properti tata letak dan tidak ada pengulangan yang akan terjadi jika tata letak saat ini tidak kotor.

Masalah muncul ketika Anda melakukan 1 dan 2 berturut-turut. Pengaktifan ulang dipaksa untuk memuaskan kueri Anda dengan informasi yang akurat.

Sepengetahuan saya, Anda benar bahwa memiliki leluhur yang benar-benar diposisikan harus membatasi pengulangan dari "penyebaran" ke seluruh dokumen (induk dari leluhur yang benar-benar diposisikan tidak akan mengalir). Semua benda di dalam leluhur yang benar-benar diposisikan masih akan mengalir!

Adapun solusi untuk masalah Anda ya ada. Atur mekanisme cache, seperti ini (pseudocode):

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

Anda dapat menggunakannya div.getClientHeight() dari pada div.clientHeight sebanyak yang Anda inginkan dan hanya penggunaan pertama yang akan memicu reflow (jika kotor).

Tentunya, sejalan dengan saran pertama, Anda juga dapat mengajukan permintaan klien secara artifisial untuk semua div dalam satu batch (= satu reflow) dan Anda tidak memiliki masalah lagi setelah itu.

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

6
2017-11-06 15:33



Reflow diantrekan setiap kali DOM berubah tetapi hanya dieksekusi ketika salah satu:

  1. Tidak ada lagi javascript untuk diproses (akhir skrip) atau

  2. Saat Anda meminta nilai terhitung yang harus dirender seperti clientHeight.

Jadi, untuk menghindari perubahan, Anda harus mengikuti aturan berikut

  • Jangan kueri DOM saat Anda mengubahnya dan

  • Jangan mengubah DOM ketika Anda ingin menanyakannya

Dalam praktik ini berarti Anda harus mengelompokkan semua operasi kueri Anda di akhir skrip setelah Anda selesai dengan memodifikasi DOM. Melakukan hal ini hanya akan mengalir sekali untuk ribuan elemen, bukan ribuan kali untuk setiap elemen.


22
2017-11-06 15:29