Dalam acara DOM browser, beberapa acara akan dipicu terus menerus dengan operasi pengguna. Misalnya: Ubah mengubah jendela browser, gulir halaman browser, dan mousemove. Artinya, ketika pengguna memicu operasi browser ini, jika metode penanganan acara yang sesuai terikat pada skrip, metode ini akan dipicu terus menerus.
Ini bukan yang kita inginkan, karena kadang -kadang jika metode penanganan peristiwa relatif besar, operasi DOM seperti kompleks, dan terus -menerus memicu peristiwa semacam itu akan menyebabkan kerugian kinerja, mengakibatkan penurunan pengalaman pengguna (respons UI lambat, browser macet, dll.). Jadi biasanya kami akan menambahkan logika ke acara yang sesuai untuk menunda eksekusi.
Secara umum, kami menggunakan kode berikut untuk mengimplementasikan fungsi ini:
var count = 0; function testfn () {console.log (count ++); } // Ketika browser mengubah ukuran // 1. Hapus timer sebelumnya // 2. Tambahkan timer untuk menunda fungsi nyata testfn dengan 100 milidetik untuk memicu window.onresize = function () {var timer = null; ClearTimeout (timer); timer = setTimeout (function () {testfn ();}, 100);};Siswa yang cermat akan menemukan bahwa kode di atas sebenarnya salah. Ini adalah masalah yang akan dibuat oleh para pemula: Nilai pengembalian fungsi SetTimeout harus disimpan dalam variabel global relatif, jika tidak timer baru akan dihasilkan setiap kali mengubah ukuran diubah ukurannya, yang tidak akan mencapai efek yang kami kirim.
Jadi kami memodifikasi kode:
var timer = null; window.onresize = function () {clearTimeout (timer); timer = setTimeout (function () {testfn ();}, 100);};Pada saat ini, kode tersebut normal, tetapi ada masalah baru lainnya - timer variabel global dihasilkan. Ini adalah sesuatu yang tidak ingin kami lihat. Jika halaman ini memiliki fungsi lain, itu juga disebut timer. Kode yang berbeda akan menyebabkan konflik sebelumnya. Untuk mengatasi masalah ini, kita perlu menggunakan fitur bahasa JavaScript: penutupan penutupan. Pembaca dapat belajar tentang pengetahuan terkait di MDN. Kode yang dimodifikasi adalah sebagai berikut:
/*** Metode throttling fungsi* @param fungsi fn penundaan fungsi panggilan* @param nomor tunda berapa lama metode penundaan* @return untuk menunda eksekusi*/var throttle = fungsi (fn, tunda) {var timer = null; return function () {clearTimeout (timer); timer = setTimeout (function () {fn ();}, tunda); }}; window.onresize = throttle (testfn, 200, 1000);Kami menggunakan fungsi penutupan (throttle throttling) untuk menempatkan timer secara internal dan mengembalikan fungsi pemrosesan penundaan. Dengan cara ini, variabel timer tidak terlihat ke luar, tetapi variabel timer juga dapat diakses ketika fungsi penundaan internal dipicu.
Tentu saja, metode penulisan ini tidak mudah untuk dipahami oleh pemula. Kita dapat mengubah metode penulisan untuk memahami:
var throttle = function (fn, delay) {var timer = null; return function () {clearTimeout (timer); timer = setTimeout (function () {fn ();}, tunda); }}; var f = throttle (testfn, 200); window.onresize = function () {f ();};Berikut adalah sudut pandang: fungsi yang dikembalikan oleh throttle setelah dipanggil adalah fungsi nyata yang perlu dipanggil ketika onressize dipicu
Sekarang tampaknya metode ini dekat dengan kesempurnaan, tetapi tidak demikian halnya dalam penggunaan aktual. Misalnya:
Jika pengguna terus mengubah ukuran jendela browser, fungsi pemrosesan penundaan tidak akan dieksekusi sekali
Jadi kita perlu menambahkan fungsi lain: Ketika pengguna memicu mengubah ukuran, itu harus dipicu setidaknya sekali dalam periode waktu tertentu. Karena dalam periode waktu tertentu, kondisi penilaian ini dapat memakan waktu milidetik saat ini, dan setiap fungsi panggilan mengurangi waktu saat ini dari waktu panggilan terakhir, dan kemudian menilai bahwa jika perbedaannya lebih besar dari periode waktu tertentu, itu akan dikirim secara langsung, jika tidak, ia akan tetap mengikuti logika penundaan batas waktu.
Apa yang perlu ditunjukkan dalam kode berikut adalah:
1. Fungsi variabel sebelumnya mirip dengan timer. Keduanya direkam pengidentifikasi terakhir dan harus berupa variabel global relatif.
2. Jika proses logika mengikuti logika "dipicu setidaknya sekali", maka panggilan fungsi harus diselesaikan untuk mengatur ulang sebelum waktu saat ini. Sederhananya, ini adalah: dibandingkan dengan yang terakhir kali, sebenarnya yang saat ini.
/*** Fungsi Metode Throttling* @param Fungsi FN Delay Call Function* @param Nomor Tunda Berapa lama penundaan* @param nomor setidaknya berapa lama dipicu* @Return Function Metode untuk menunda eksekusi*/var throttle = function (fn, tunda, setidaknya) {var timer = null; var sebelumnya = null; return function () {var now = +new date (); if (! sebelumnya) sebelumnya = sekarang; if (sekarang - sebelumnya> setidaknya) {fn (); // Setel ulang waktu mulai terakhir hingga akhir waktu ini sebelumnya = sekarang; } else {cleartimeout (timer); timer = setTimeout (function () {fn ();}, tunda); }}};praktik:
Kami mensimulasikan adegan pelambatan ketika sebuah jendela menggulir, yaitu, ketika pengguna menggulir halaman ke bawah, kami perlu mencekik beberapa metode, seperti: menghitung posisi DOM, dll., Yang membutuhkan pengoperasian elemen DOM yang berkelanjutan.
Kode lengkapnya adalah sebagai berikut:
<! Doctype html> <html lang = "en"> <head> <meta charset = "utf-8"> <itement> throttle </ title> </pead> <body> <div style = "tinggi: 5000px"> <div id = "Demo" style = "posisi: tetap;"> </div> </div> varel = demo = gaya = "Posisi: fixed;"> </div> </div> var lrip = Demo = Posisi = Posisi: Fixed; "> </Div> </Div> DOCKED = DOKUM = POSED = POSITE; function testfn () {demo.innerHtml += 'testfn disebut' +++ count +'waktu <br>';} var throttle = fungsi (fn, tunda, setidaknya) {var timer = null; var sebelumnya = null; return function () {var now = +new date (); if (! sebelumnya) sebelumnya = sekarang; if (setidaknya && sekarang - sebelumnya> setidaknya) {fn (); // Setel ulang waktu mulai terakhir hingga akhir waktu ini sebelumnya = sekarang; ClearTimeout (timer); } else {cleartimeout (timer); timer = setTimeout (function () {fn (); sebelumnya = null;}, tunda); }}}}; window.onscroll = throttle (testfn, 200); // window.onscroll = throttle (testfn, 500, 1000); </script> </body> </html>Kami menggunakan dua kasus untuk menguji efeknya, yaitu menambahkan setidaknya memicu setidaknya setidaknya dan tidak menambahkan:
// case 1window.onscroll = throttle (testfn, 200); // case 2window.onscroll = throttle (testfn, 200, 500);
Kasus 1 dimanifestasikan sebagai: testfn tidak akan dipanggil selama proses pengguliran halaman (tidak dapat dihentikan), dan itu akan dipanggil sekali sampai berhenti, yang berarti bahwa pengaturan terakhir dalam throttle dieksekusi, dan efeknya seperti yang ditunjukkan pada gambar (lihat gambar GIF asli):
Kasus 2 dimanifestasikan sebagai: Selama proses pengguliran halaman (tidak dapat dihentikan), testfn akan ditunda 500ms untuk pertama kalinya (dari setidaknya logika penundaan), dan kemudian menjalankan setidaknya setiap 500ms, efeknya seperti yang ditunjukkan pada gambar
Sejauh ini, hasil yang ingin kami capai pada dasarnya telah selesai. Pembaca dapat memikirkan beberapa optimasi tambahan berikutnya sendiri, seperti: berfungsi menunjuk ini, penghematan nilai pengembalian, dll.
Di atas adalah semua konten artikel ini. Saya berharap ini akan membantu untuk pembelajaran semua orang dan saya harap semua orang akan lebih mendukung wulin.com.