Chrome 105 giới thiệu hai phương thức mới trên NavigateEvent
của Navigation API (được giới thiệu trong phiên bản 102) để cải thiện các phương thức đã chứng minh là có vấn đề trong thực tế. intercept()
cho phép nhà phát triển kiểm soát trạng thái sau khi điều hướng, thay thế transitionWhile()
khó sử dụng. Phương thức scroll()
cuộn đến một neo được chỉ định trong URL, thay thế restoreScroll()
không hoạt động cho tất cả các loại điều hướng.
Trong bài viết này, tôi sẽ giải thích các vấn đề với cả hai phương pháp và cách các phương pháp mới khắc phục những vấn đề đó.
NavigateEvent.transitionWhile()
Phương thức NavigateEvent.trasitionWhile()
, được giới thiệu với Navigation API trong Chrome 102, sẽ chặn thao tác điều hướng cho các lượt chuyển đổi phía máy khách trong ứng dụng một trang. Đối số đầu tiên của hàm này là một lời hứa báo hiệu cho trình duyệt và các phần khác của ứng dụng web rằng quá trình tải đã hoàn tất.
Cách này không hiệu quả trong thực tế. Hãy xem xét mẫu lập trình phổ biến sau:
event.transitionWhile((async () => {
doSyncStuff();
await doAsyncStuff();
})());
Mã này tương đương về mặt chức năng với mã bên dưới. Điều này khiến một số phần của thao tác điều hướng chạy trước khi API nhận biết rằng nhà phát triển có ý định chặn thao tác điều hướng.
doSyncStuff();
event.transitionWhile((async () => {
await doAsyncStuff();
})());
Một ví dụ về trường hợp điều này có thể làm hỏng ứng dụng là trong logic khôi phục cuộn, trong đó ứng dụng sẽ ghi lại các vị trí cuộn sau khi DOM thay đổi, thay vì trước đó.
Những điểm thay đổi
Để thay thế transitionWhile()
, thông số kỹ thuật hiện tại sẽ giới thiệu NavigateEvent.intercept()
. Phương thức mới sẽ nhận một trình xử lý ngoài các thuộc tính focusReset
và scrollRestoration
mà transitionWhile()
hỗ trợ. Trình xử lý mới luôn chạy sau khi các thay đổi điều hướng được xác nhận và các thông tin như vị trí cuộn đã được ghi lại, tránh các vấn đề với transitionWhile()
.
Phương thức transitionWhile()
vẫn hoạt động nhưng không còn được dùng nữa và sẽ bị xoá trong Chrome 108.
Sử dụng intercept()
NavigateEvent.intercept()
có các quy định hạn chế giống như transitionWhile()
, vì không thể gọi trên tất cả các sự kiện điều hướng. Không thể chặn thao tác điều hướng giữa các nguồn gốc cũng như không thể chặn thao tác di chuyển giữa các tài liệu. Thao tác này sẽ gửi một DOMException
thuộc loại "SecurityError"
.
Để sử dụng intercept()
, bạn chỉ cần truyền trình xử lý tuỳ chỉnh khi gọi trình xử lý đó.
navigation.addEventListener("navigate", event => {
event.intercept({
async handler() {
doSyncStuff();
await doAsyncStuff();
}
});
});
NavigateEvent.scroll()
Một thao tác điều hướng như thao tác từ đầu trang đến một neo (gọi là thao tác di chuyển từ /a
đến /a#id
) được trình duyệt xử lý hoàn toàn ngay cả trong ứng dụng một trang. Tuy nhiên, thao tác điều hướng đến một neo trên một "trang" khác (/a
đến /b#id
) rất đơn giản đối với ứng dụng nhiều trang, nhưng lại phức tạp hơn đối với ứng dụng một trang. Ứng dụng phải chặn thao tác điều hướng đến /b#id
bằng NavigateEvent.transitionWhile()
, sau đó gọi NavigateEvent.restoreScroll()
để đưa neo vào chế độ xem. Như đã nêu ở trên, hiện tại, việc này rất khó thực hiện.
Những điểm thay đổi
Trong các ứng dụng một trang, giờ đây, bạn có thể kiểm soát xem trình duyệt có xử lý việc cuộn đến một neo hay không hoặc mã của bạn có xử lý việc này hay không.
Sử dụng scroll()
Theo mặc định, trình duyệt sẽ cố gắng tự động xử lý thao tác cuộn sau khi trình xử lý chặn đã hoàn tất. Nếu bạn muốn tự xử lý thao tác cuộn, hãy đặt scroll
thành "manual"
, sau đó gọi NavigateEvent.scroll()
khi trình duyệt cố gắng đặt vị trí cuộn.
navigation.addEventListener("manual", event => {
scroll: "manual",
event.intercept({
async handler() {
doSyncStuff();
// Handle scrolling earlier than by default:
event.scroll();
await doAsyncStuff();
}
});
});
Phương thức restoreScroll()
vẫn hoạt động nhưng không còn được dùng nữa và sẽ bị xoá trong Chrome 108.
Kết luận
Chúng tôi hy vọng sẽ sớm cập nhật bài viết về Navigation API. Trong thời gian chờ đợi, thông số kỹ thuật của API này chứa nhiều thông tin dành riêng cho nhà phát triển web.