Membuat tabel gulir tanpa batas tanpa pendengar acara

Mengapa itu tertinggal begitu?



Jika ketika membuat tabel besar dengan semacam animasi transisi, tidak ada lagi yang dilakukan, maka aplikasi akan tertinggal, dan pengguna akan menderita.




Dalam kebanyakan kasus, ketika kita menggunakan pendengar acara untuk membuat tabel dengan pengguliran tak terbatas, kita tidak hanya perlu melakukan perhitungan terkait dengan viewport dan tinggi baris, tetapi juga menulis banyak logika di penangan gulir untuk mencegah penggambaran ulang terlalu sering, karena setiap gulir panggilan balik akan panggil setState .


Kode akan menjadi seperti ini:


 componentDidMount() { window.addEventListener('scroll', this.handleScroll) } handleScroll(e) { // use window offset and boundingRect const { ...someAttributes } = window; const { ...someBoundingRect } = this.component // some logic prevent re-render if ( ... ) return; // do some math const newIndex = ... // and how many rows should be rendered this.setState({index: newIndex }) } 

Tetapi ada pendekatan lain untuk menerapkan pengguliran tabel yang tak terbatas, tanpa mengetahui apa pun tentang nilai-nilai jendela atau boundingRect.


Ini adalah IntersectionObserver . Definisi dari w3c :


Spesifikasi ini menjelaskan API yang dapat digunakan untuk mengetahui visibilitas dan posisi elemen DOM ("target") relatif terhadap elemen yang terkandung di dalamnya.

Saat menggunakan metode ini, Anda tidak perlu tahu ketinggian garis, bagian atas viewport, atau nilai lainnya untuk melakukan perhitungan.



Konsepnya adalah mengatur jangkar dengan indeks di setiap titik kontrol dan setiap kali jangkar dipicu, dapatkan nilai indeks dan gambar ulang tabel. Berkat ini, Anda tidak perlu melakukan sihir matematika dengan tinggi dan viewport DOM.



Pemicu jangkar untuk indeks 1


Berikan lebih banyak baris


Kode dengan IntersectionObserver akan seperti ini.



 handleSentinel = (c) => { if(!this.observer) { //  observer this.observer = new IntersectionObserver( entries => { entries.forEach(e => { //   ,    if (e.isIntersecting) { this.setState( { cursor: +e.target.getAttribute('index') } ); } }); }, { root: document.querySelector('App'), rootMargin: '-30px', } } if (!c) return; //    this.observer.observe(c) } render() { const blockNum = 5; return( ... <tbody> {MOCK_DATA.slice(0, (cursor+1) * blockNum).map(d => <Block> { //       // ,   5  d.id % blockNum === 0 ? <span ref={this.handleSentinel} index={d.id / blockNum} /> : null } </Block>)} </tbody> ... ) } 

Source: https://habr.com/ru/post/id456046/


All Articles