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.
Chromium đã chính thức ngừng sử dụng các sự kiện đột biến và dự định ngừng hỗ trợ phiên bản 127. Phiên bản này sẽ trở thành bản phát hành ổn định 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 thay đổi 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 bất kỳ 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 bất kỳ trình duyệt hiện đại nào hỗ trợ)
DOMElementNameChanged
Các sự kiện này là phần rất cũ của thông số kỹ thuật DOM cấp 2 và đã không đượ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ả cá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 việc 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 này đã không còn được dùng trong thông số kỹ thuật vào năm 2011 và một API thay thế (MutationObserver
) đã được xây dựng 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ư DOMNodeInsertedIntoDocument
và DOMNodeRemovedFromDocument
, không được hỗ trợ trong tất cả 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.
Trước tiên, những sự kiện này đang cản trở 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 góp phần giúp trình duyệt hoạt động 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.
Vì đã hơn 10 năm kể từ khi các sự kiện này chính thức không được dùng nữa, và API thay thế cũng đã có mặt trong hơn 10 năm, nên cuối cùng đã đến lúc phải loại bỏ 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
có 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 xin lưu ý rằng mã này có thể xử lý mọi trường hợp độ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.
Ống polyfill
Có một tệp polyfill tìm cách cho phép mã hiện có tiếp tục hoạt động trong khi vẫn được MutationObserver
cung cấp. Polyfill nằm trên GitHub hoặc dưới dạng một gói npm.
- https://github.com/mfreed7/mutation-events-polyfill#readme
- https://www.npmjs.com/package/mutation-events
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 cần thêm thời gian (ngoài tháng 7 năm 2024) để di chuyển mã, bạn có thể tham khảo Bản dùng thử ngừng hoạt động để tạm thời bật lại những sự kiện đó trên những 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.