Tìm hiểu gì, tại sao, và cách dùng phương thức Event Delegation trong JavaScript.
Event Delegation trong JavaScript là gì và khi nào nên dùng?
Ngắn gọn, event delegation là phương thức JavaScript cho phép bạn tương tác với các phần tử con bằng cách chỉ dùng một trình lắng nghe sự kiện (event listener) trên phần tử cha. Với event delegation, bạn tránh việc phải gắn trình xử lý sự kiện cho từng phần tử con, nhưng vẫn có thể tìm và thao tác chúng.
Bạn sẽ thấy tại sao điều này mạnh mẽ ngay.
Giả sử bạn có danh sách các mục bên trong một danh sách. Khi người dùng click vào bất kỳ mục nào, bạn muốn có điều gì đó xảy ra.
Hãy xem hai cách khác nhau làm điều đó.
Gắn trình lắng nghe sự kiện cho từng phần tử
Cách phổ biến để truy cập các mục phần tử riêng lẻ trên danh sách là lặp qua chúng ví dụ với vòng lặp for. Rồi gắn trình lắng nghe sự kiện cho từng phần tử:
let allExerciseItems = document.querySelectorAll(".exercise-item") for (let exerciseItem of allExerciseItems) { exerciseItem.addEventListener("click", function(event) { // Làm gì đó với phần tử con mục tiêu event.target.classList.toggle("exercise-complete") }); }
Ví dụ
https://codepen.io/StrengthandFreedom/pen/KBZezV/
Truy cập mục với Event Delegation
Event delegation hoàn toàn khác với ví dụ vòng lặp for bạn thấy ở trên. Thay vì lặp (duyệt) qua từng phần tử muốn truy cập, chúng ta chỉ nhắm đến phần tử cha, như sau:
// Lấy phần tử cha, thêm trình lắng nghe click document.querySelector(".exercise-list").addEventListener("click", function(event) { if(event.target.classList.contains('exercise-item')) { // Làm gì đó với phần tử con mục tiêu event.target.classList.toggle('exercise-complete') } })
Ví dụ CodePen. Lưu ý: thay vì classList.contains bạn có thể dùng API element.matches matches() nếu cần độ linh hoạt selector hơn.
Như bạn thấy, kết quả y hệt. Khi click vào bất kỳ mục bài tập nào, chúng toggle class exercise-complete. Khác biệt là phương pháp đạt được kết quả.
Tại sao nên dùng event delegation thay vì event handling + vòng lặp for?
Hãy thảo luận tiếp!
Event Delegation và Hiệu suất
Hãy tưởng tượng bạn xử lý ứng dụng web có hàng trăm hoặc hàng nghìn phần tử được tạo động mỗi ngày, giờ, thậm chí mỗi phút. Ví dụ có thể là lịch đặt phòng khách sạn. Hoặc nền tảng mạng xã hội như Twitter yêu cầu cập nhật trực tiếp thường xuyên để mang lại trải nghiệm người dùng tối ưu.
Nếu mọi phần tử trong UI web của bạn đều gắn trình lắng nghe sự kiện, kịch bản này nhanh chóng trở nên tốn tài nguyên phần cứng.
Tất cả các trình lắng nghe sự kiện đó có thể ngốn CPU của người dùng. Chúng có thể gây ra lượng tham chiếu hàm khổng lồ nằm trong bộ nhớ. Điều này có thể gây rò rỉ bộ nhớ và giảm hiệu suất tổng thể.
Tôi không rành lắm về GC (Garbage Collection). Tôi có đặc quyền chỉ viết JavaScript (ngôn ngữ lập trình cấp cao). Nhưng một điều tôi biết, GC trong trình duyệt có thể khó dự đoán do nhiều trình duyệt khác nhau (Chrome, FireFox v.v). Và, tất nhiên, vô số thiết bị (smartphone, laptop v.v.).
Garbage Collection (Thu gom rác)
Ngắn gọn, Garbage Collection là loại quản lý bộ nhớ máy tính. Bộ gom rác cố gắng xóa mã cũ/không dùng nữa chỉ ngồi đó và chiếm bộ nhớ máy tính. Có vô số bộ gom rác khác nhau cho các ngôn ngữ và hệ thống khác nhau.
Việc gắn trình lắng nghe sự kiện cho mọi thứ, như ví dụ vòng lặp, sẽ tăng lượng garbage collection ứng dụng web cần. Điều này gần như chắc chắn làm giảm hiệu suất.
Thường thì hiệu quả hơn khi có một trình lắng nghe sự kiện trên phần tử cha lắng nghe tất cả click trên các phần tử con, thay vì gắn trình lắng nghe cho từng phần tử con riêng lẻ.