Xử lý sự kiện trong javascript pdf

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

  1. 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
  2. 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
  3. 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
  4. 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

  1. 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ó
  2. 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

Xử lý sự kiện JavaScript là gì?

Trình xử lý sự kiện JavaScript . Những việc nên làm mỗi khi tải trang. Những việc nên làm khi đóng trang. Hành động nên được thực hiện khi người dùng nhấp vào nút. Event handlers can be used to handle and verify user input, user actions, and browser actions: Things that should be done every time a page loads. Things that should be done when the page is closed. Action that should be performed when a user clicks a button.

8 loại sự kiện JavaScript là gì?

Các loại sự kiện JavaScript .
Sự kiện giao diện người dùng. Những điều này xảy ra do bất kỳ tương tác nào với cửa sổ trình duyệt chứ không phải trang HTML. .
Tập trung và làm mờ các sự kiện. .
sự kiện chuột. .
sự kiện bàn phím. .
Sự kiện biểu mẫu. .
Sự kiện đột biến và người quan sát. .
sự kiện HTML5. .
sự kiện CSS

Xử lý sự kiện và các loại là gì?

Xử lý sự kiện là gì? . Cơ chế này có mã được gọi là trình xử lý sự kiện được thực thi khi một sự kiện xảy ra. Java Sử dụng Mô hình Sự kiện Ủy quyền để xử lý các sự kiện. the mechanism that controls the event and decides what should happen if an event occurs. This mechanism have the code which is known as event handler that is executed when an event occurs. Java Uses the Delegation Event Model to handle the events.

Trình xử lý sự kiện trong JavaScript đưa ra ví dụ là gì?

Trình xử lý sự kiện này gọi mã JavaScript khi hành động nhấp xảy ra trên phần tử HTML. e. g. , khi chúng ta nhấp vào nút, liên kết được đẩy, hộp kiểm kiểm tra hoặc bản đồ hình ảnh được chọn, nó có thể kích hoạt trình xử lý sự kiện onClick. Trình xử lý sự kiện này gọi mã JavaScript khi cửa sổ hoặc hình ảnh tải xong

Chủ đề