Các sự kiện đột biến sẽ bị xoá khỏi Chrome

Thông báo về việc ngừng sử dụng và kế hoạch xoá các sự kiện đột biến, đồng thời chia sẻ cách di chuyển mã trước khi xoá vào tháng 7 năm 2024.

Mason Freed
Mason Freed

Chromium đã chính thức ngừng sử dụng các sự kiện đột biến và có kế hoạch ngừng hỗ trợ kể từ phiên bản 127, phiên bản này sẽ được phát hành chính thức vào ngày 23 tháng 7 năm 2024. Bài đăng này giải thích lý do chúng tôi xoá các sự kiện đột biến và cung cấp lộ trình di chuyển trước khi các sự kiện này bị xoá khỏi trình duyệt.

Sự kiện đột biến là gì?

Sự kiện đột biến là tên của tập hợp các sự kiện sau:

  • DOMNodeInserted
  • DOMNodeRemoved
  • DOMSubtreeModified
  • DOMCharacterDataModified
  • DOMNodeInsertedIntoDocument
  • DOMNodeRemovedFromDocument
  • (Không có trình duyệt hiện đại nào hỗ trợ) DOMAttrModified
  • (Không có trình duyệt hiện đại nào hỗ trợ) DOMAttributeNameChanged
  • (Không có trình duyệt hiện đại nào hỗ trợ) DOMElementNameChanged

Những sự kiện này là một phần rất cũ của thông số kỹ thuật DOM cấp 2 và đã không còn được dùng nữa kể từ năm 2011. Các giao diện này đã được thay thế bằng giao diện MutationObserver. Giao diện này đã được hỗ trợ trong tất cả trình duyệt hiện đại kể từ năm 2013.

Nhật ký sự kiện thay đổi

Sự kiện đột biến nghe có vẻ là một ý tưởng hay từ lâu, nhưng hóa ra lại có một số lỗi nghiêm trọng:

  • Chúng dài dòng và kích hoạt quá thường xuyên. Một sự kiện sẽ được kích hoạt cho mỗi nút bị xoá.
  • Các sự kiện này chậm do quá trình truyền sự kiện và vì chúng ngăn chặn nhiều hoạt động tối ưu hoá thời gian chạy UA.
  • Các lỗi này thường gây ra sự cố. Đây là nguồn gốc của nhiều sự cố và lỗi bảo mật trong trình duyệt, vì trình nghe sự kiện có thể thay đổi toàn bộ DOM bên dưới một thao tác DOM đang chạy.

Do những lỗi này, các sự kiện đã không được dùng nữa trong thông số kỹ thuật năm 2011 và một API thay thế (MutationObserver) đã được tạo vào năm 2012. API mới đã được triển khai và hoạt động được hơn 10 năm tại thời điểm này.

Lý do xoá sự kiện đột biến

Khả năng hỗ trợ sự kiện đột biến thay đổi tuỳ theo trình duyệt. Một số sự kiện, chẳng hạn như DOMNodeInsertedIntoDocumentDOMNodeRemovedFromDocument, không được hỗ trợ trong một số trình duyệt. Đối với các sự kiện khác, hành vi cụ thể sẽ khác nhau do không có quy cách nào được thoả thuận. Tuy nhiên, có thể bạn sẽ thắc mắc: tại sao không để các tệp đó ở đó, vì chúng đã "hoàn tất" và chỉ làm chậm các trang sử dụng chúng? Câu trả lời có hai phần.

Thứ nhất, những sự kiện này đang kìm hãm nền tảng web. Khi web phát triển và các API mới được thêm vào, bạn phải tính đến sự tồn tại của các API cũ này. Đôi khi, chỉ cần cần hỗ trợ các sự kiện này là có thể khiến API mới không được đề xuất. Ví dụ: đã có một yêu cầu lâu nay để ngăn các phần tử <iframe> tải lại khi được di chuyển trong DOM. Tuy nhiên, một phần do sự tồn tại của các sự kiện đột biến, nên nỗ lực đó được coi là quá khó để đạt được và yêu cầu đã bị đóng.

Những sự kiện này tiếp tục cản trở việc làm cho trình duyệt nhanh hơn. Ngay cả khi trình duyệt có các tính năng tối ưu hoá để cố gắng tránh bị phạt về hiệu suất trên các trang không sử dụng sự kiện đột biến, mọi thứ vẫn chưa hoàn hảo. Bạn vẫn cần kiểm tra ở nhiều nơi đối với trình nghe Sự kiện đột biến. Bạn vẫn cần viết mã một cách rất thận trọng vì những sự kiện này có thể thay đổi DOM theo những cách đáng ngạc nhiên.

Đã hơn 10 năm kể từ khi các sự kiện này không còn được dùng nữa và API thay thế cũng đã có sẵn trong hơn 10 năm, đã đến lúc loại bỏ hoàn toàn các sự kiện đột biến khỏi trình duyệt.

Cách di chuyển

Thay vào đó, hãy sử dụng MutationObserver

Tài liệu về MutationObserver nằm trên MDN và khá đầy đủ. Việc thay thế cơ sở mã của bạn phụ thuộc vào cách các sự kiện này đang được sử dụng, nhưng ví dụ:

// Old mutation event usage:  
target.addEventListener('DOMNodeInserted',event => doSomething(event.target));

// Replacement mutation observer code:  
const observer = new MutationObserver(mutationList =>  
  mutationList.filter(m => m.type === 'childList').forEach(m => {  
    m.addedNodes.forEach(doSomething);  
  }));  
observer.observe(target,{childList: true, subtree: true});  

Mặc dù mã MutationObserver có vẻ lớn hơn mã trình nghe sự kiện DOMNodeInserted ban đầu, nhưng hãy lưu ý rằng mã này có thể xử lý tất cả các đột biến xảy ra trên toàn bộ cây trong một lệnh gọi, thay vì yêu cầu nhiều lệnh gọi đến trình xử lý sự kiện.

Polyfill

Có một polyfill cố gắng cho phép mã hiện có tiếp tục hoạt động, trong khi được cung cấp bởi MutationObserver. Polyfill nằm trên GitHub hoặc dưới dạng gói npm.

Tiến trình và thông tin về bản dùng thử ngừng hoạt động

Sự kiện đột biến sẽ bị xoá khỏi Chrome 127 đối với tất cả người dùng*. Phiên bản này sẽ chuyển sang bản phát hành ổn định vào ngày 23 tháng 7 năm 2024. Các sự kiện này sẽ bắt đầu bị xoá khỏi các kênh Canary, Dev và Beta sớm hơn thời điểm đó để cảnh báo sớm.

  • Nếu bạn cần thêm thời gian (sau tháng 7 năm 2024) để di chuyển mã, thì bạn có thể sử dụng Bản dùng thử về việc ngừng sử dụng để tạm thời bật lại các sự kiện trên các trang web được chỉ định. Ngoài ra, còn có một Chính sách doanh nghiệp có tên là MutationEventsEnabled hoạt động theo cách tương tự đối với người dùng doanh nghiệp. Cả hai lựa chọn này đều cho phép bạn thêm khoảng 9 tháng để di chuyển nếu cần.