Chụp và sủi bọt cho phép chúng tôi triển khai một trong những mẫu xử lý sự kiện mạnh mẽ nhất được gọi là ủy quyền sự kiện
Ý tưởng là nếu chúng ta có nhiều phần tử được xử lý theo cách tương tự, thì thay vì chỉ định một trình xử lý cho từng phần tử – chúng ta đặt một trình xử lý duy nhất trên tổ tiên chung của chúng
Trong trình xử lý, chúng tôi nhận được let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }8 để xem sự kiện thực sự xảy ra ở đâu và xử lý nó
Hãy xem một ví dụ – biểu đồ Bát quái phản ánh triết học Trung Quốc cổ đại
Đây rồi
HTML là như thế này
<table> <tr> <th colspan="3"><em>Bagua</em> Chart: Direction, Element, Color, Meaning</th> </tr> <tr> <td class="nw"><strong>Northwest</strong><br>Metal<br>Silver<br>Elders</td> <td class="n">...</td> <td class="ne">...</td> </tr> <tr>...2 more lines of this kind...</tr> <tr>...2 more lines of this kind...</tr> </table>
Bảng có 9 ô, nhưng có thể có 99 hoặc 9999, không quan trọng
Nhiệm vụ của chúng ta là đánh dấu một ô let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }9 khi nhấp chuột
Thay vì gán một trình xử lý let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }0 cho mỗi let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }9 (có thể nhiều) – chúng ta sẽ thiết lập trình xử lý “bắt tất cả” trên phần tử let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }2
Nó sẽ sử dụng let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }8 để lấy phần tử được nhấp và đánh dấu nó
Mật mã
let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }
Mã như vậy không quan tâm có bao nhiêu ô trong bảng. Chúng tôi có thể tự động thêm/xóa let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }9 bất kỳ lúc nào và tính năng đánh dấu vẫn hoạt động
Tuy nhiên, có một nhược điểm
Nhấp chuột có thể không xảy ra trên let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }9, nhưng bên trong nó
Trong trường hợp của chúng tôi, nếu chúng tôi xem bên trong HTML, chúng tôi có thể thấy các thẻ lồng nhau bên trong let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }9, chẳng hạn như let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }7
<td> <strong>Northwest</strong> ... </td>
Đương nhiên, nếu một nhấp chuột xảy ra trên let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }7 đó thì nó sẽ trở thành giá trị của let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }8
Trong trình xử lý <td> <strong>Northwest</strong> ... </td>0, chúng ta nên lấy let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }8 đó và tìm hiểu xem nhấp chuột có nằm trong let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }9 hay không
Đây là mã cải tiến
________số 8
giải thích
- Phương thức <td> <strong>Northwest</strong> ... </td>3 trả về tổ tiên gần nhất khớp với bộ chọn. Trong trường hợp của chúng tôi, chúng tôi tìm kiếm let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }9 trên đường đi lên từ phần tử nguồn
- Nếu let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }8 không nằm trong bất kỳ let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }9 nào, thì cuộc gọi sẽ trả về ngay lập tức, vì không có gì để làm
- Trong trường hợp các bảng lồng nhau, let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }8 có thể là một let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }9, nhưng nằm bên ngoài bảng hiện tại. Vì vậy, chúng tôi kiểm tra xem đó có thực sự là bảng của chúng tôi không let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }9
- Và, nếu đúng như vậy, thì hãy đánh dấu nó
Kết quả là, chúng tôi có một mã đánh dấu nhanh, hiệu quả, không quan tâm đến tổng số let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }9 trong bảng
Có những cách sử dụng khác cho ủy quyền sự kiện
Giả sử, chúng tôi muốn tạo một menu có các nút “Lưu”, “Tải”, “Tìm kiếm”, v.v. Và có một đối tượng với các phương thức table. title = function(event) { let td = event.target.closest('td'); // (1) if (!td) return; // (2) if (!table.contains(td)) return; // (3) highlight(td); // (4) };1, table. title = function(event) { let td = event.target.closest('td'); // (1) if (!td) return; // (2) if (!table.contains(td)) return; // (3) highlight(td); // (4) };2, table. title = function(event) { let td = event.target.closest('td'); // (1) if (!td) return; // (2) if (!table.contains(td)) return; // (3) highlight(td); // (4) };3… Làm cách nào để khớp chúng?
Ý tưởng đầu tiên có thể là gán một trình xử lý riêng cho từng nút. Nhưng có một giải pháp tao nhã hơn. Chúng tôi có thể thêm trình xử lý cho toàn bộ menu và thuộc tính table. title = function(event) { let td = event.target.closest('td'); // (1) if (!td) return; // (2) if (!table.contains(td)) return; // (3) highlight(td); // (4) };4 cho các nút có phương thức gọi
let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }4
Trình xử lý đọc thuộc tính và thực thi phương thức. Hãy xem ví dụ làm việc
let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }5
Xin lưu ý rằng table. title = function(event) { let td = event.target.closest('td'); // (1) if (!td) return; // (2) if (!table.contains(td)) return; // (3) highlight(td); // (4) };5 bị ràng buộc với table. title = function(event) { let td = event.target.closest('td'); // (1) if (!td) return; // (2) if (!table.contains(td)) return; // (3) highlight(td); // (4) };6 trong table. title = function(event) { let td = event.target.closest('td'); // (1) if (!td) return; // (2) if (!table.contains(td)) return; // (3) highlight(td); // (4) };7. Điều đó rất quan trọng, vì nếu không thì table. title = function(event) { let td = event.target.closest('td'); // (1) if (!td) return; // (2) if (!table.contains(td)) return; // (3) highlight(td); // (4) };6 bên trong nó sẽ tham chiếu đến phần tử DOM (table. title = function(event) { let td = event.target.closest('td'); // (1) if (!td) return; // (2) if (!table.contains(td)) return; // (3) highlight(td); // (4) };9), chứ không phải đối tượng let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }40 và let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }41 sẽ không phải là thứ chúng ta cần
Vì vậy, ủy quyền mang lại cho chúng ta những lợi thế gì ở đây?
- Chúng tôi không cần phải viết mã để chỉ định trình xử lý cho từng nút. Chỉ cần tạo một phương thức và đặt nó vào phần đánh dấu
- Cấu trúc HTML linh hoạt, chúng ta có thể thêm/bớt các nút bất cứ lúc nào
Chúng ta cũng có thể sử dụng các lớp let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }42, let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }43, nhưng thuộc tính table. title = function(event) { let td = event.target.closest('td'); // (1) if (!td) return; // (2) if (!table.contains(td)) return; // (3) highlight(td); // (4) };4 tốt hơn về mặt ngữ nghĩa. Và chúng ta cũng có thể sử dụng nó trong các quy tắc CSS
Chúng ta cũng có thể sử dụng ủy quyền sự kiện để thêm “hành vi” vào các phần tử theo cách khai báo, với các thuộc tính và lớp đặc biệt
Mẫu có hai phần
- Chúng tôi thêm một thuộc tính tùy chỉnh vào một phần tử mô tả hành vi của nó
- Trình xử lý trên toàn bộ tài liệu theo dõi các sự kiện và nếu một sự kiện xảy ra trên một phần tử được phân bổ – hãy thực hiện hành động
Chẳng hạn, ở đây thuộc tính let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }45 thêm một hành vi. “tăng giá trị khi nhấp chuột” vào các nút
let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }7
Nếu chúng ta nhấp vào một nút - giá trị của nó sẽ tăng lên. Không phải các nút, nhưng cách tiếp cận chung là quan trọng ở đây
Có thể có bao nhiêu thuộc tính với let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }45 tùy thích. Chúng tôi có thể thêm những cái mới vào HTML bất cứ lúc nào. Sử dụng ủy quyền sự kiện, chúng tôi đã “mở rộng” HTML, thêm một thuộc tính mô tả một hành vi mới
Đối với trình xử lý cấp tài liệu – luôn luôn let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }47
Khi chúng ta chỉ định một trình xử lý sự kiện cho đối tượng let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }48, chúng ta nên luôn sử dụng let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }47, không phải let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }50, vì điều này sẽ gây ra xung đột. trình xử lý mới ghi đè lên cái cũ
Đối với các dự án thực tế, việc có nhiều trình xử lý trên let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }48 được đặt bởi các phần khác nhau của mã là điều bình thường
Thêm một ví dụ về hành vi. Nhấp chuột vào phần tử có thuộc tính let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }52 sẽ hiển thị/ẩn phần tử có thuộc tính let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }53 đã cho
let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }6
Hãy ghi lại một lần nữa những gì chúng tôi đã làm. Bây giờ, để thêm chức năng chuyển đổi cho một phần tử – không cần biết JavaScript, chỉ cần sử dụng thuộc tính let selectedTd; table. title = function(event) { let target = event.target; // where was the click? if (target.tagName != 'TD') return; // not on TD? Then we're not interested highlight(target); // highlight it }; function highlight(td) { if (selectedTd) { // remove the existing highlight if any selectedTd.classList.remove('highlight'); } selectedTd = td; selectedTd.classList.add('highlight'); // highlight the new td }52
Điều đó có thể trở nên thực sự tiện lợi – không cần phải viết JavaScript cho mọi phần tử như vậy. Chỉ cần sử dụng các hành vi. Trình xử lý cấp tài liệu làm cho nó hoạt động với bất kỳ thành phần nào của trang