Dữ liệu đầu vào sắp xuất hiện trên Trình tổng hợp
Đây là phần cuối trong loạt blog gồm 4 phần về bên trong Chrome; điều tra cách nó xử lý mã của chúng tôi để hiển thị trang web. Trong bài đăng trước, chúng ta đã xem xét quy trình kết xuất và tìm hiểu về trình tổng hợp. Trong bài đăng này, chúng tôi sẽ xem xét cách trình tổng hợp cho phép tương tác mượt mà khi người dùng có hoạt động đầu vào.
Nhập sự kiện từ góc nhìn của trình duyệt
Khi bạn nghe thấy "sự kiện nhập" bạn có thể chỉ nghĩ đến việc nhập vào hộp văn bản hoặc nhấp chuột, nhưng từ quan điểm của trình duyệt, dữ liệu nhập có nghĩa là bất kỳ cử chỉ nào của người dùng. Cuộn con lăn chuột là một phương thức nhập sự kiện và chạm hoặc di chuột qua cũng là một sự kiện đầu vào.
Khi cử chỉ của người dùng như chạm vào màn hình diễn ra, quá trình của trình duyệt là quá trình nhận
cử chỉ đầu tiên. Tuy nhiên, quá trình xử lý của trình duyệt chỉ biết được vị trí cử chỉ đó diễn ra kể từ
nội dung bên trong một thẻ được xử lý bởi quá trình kết xuất đồ hoạ. Vì vậy, quy trình của trình duyệt sẽ gửi sự kiện
loại (như touchstart
) và các toạ độ của nó vào quy trình kết xuất. Quá trình kết xuất xử lý
một cách thích hợp bằng cách tìm mục tiêu sự kiện và chạy trình nghe sự kiện được đính kèm.
Trình tổng hợp nhận sự kiện nhập
Trong bài đăng trước, chúng ta đã xem xét cách trình tổng hợp có thể xử lý thao tác cuộn suôn sẻ bằng cách tổng hợp các lớp đã tạo điểm ảnh. Nếu không có trình nghe sự kiện đầu vào nào được đính kèm vào trang, thì luồng trình tổng hợp có thể tạo một khung tổng hợp mới hoàn toàn độc lập với luồng chính. Nhưng nếu một số sự kiện người nghe có được tương tác với trang không? Làm cách nào để trình tổng hợp tìm hiểu xem sự kiện đó có cần cần xử lý không?
Tìm hiểu về khu vực không thể cuộn nhanh
Vì chạy JavaScript là công việc của luồng chính, nên khi một trang được kết hợp, luồng trình tổng hợp đánh dấu một vùng của trang có trình xử lý sự kiện được đính kèm là "Khu vực không thể cuộn nhanh". Theo khi có thông tin này, luồng trình tổng hợp có thể đảm bảo gửi sự kiện đầu vào đến luồng chính nếu sự kiện xảy ra ở khu vực đó. Nếu sự kiện đầu vào đến từ bên ngoài khu vực này, thì luồng trình tổng hợp tiến hành quá trình tổng hợp khung mới mà không cần đợi luồng chính.
Hãy lưu ý khi bạn viết trình xử lý sự kiện
Một mẫu xử lý sự kiện phổ biến trong quá trình phát triển web là uỷ quyền sự kiện. Vì bong bóng sự kiện, bạn có thể đính kèm một trình xử lý sự kiện ở phần tử trên cùng và uỷ quyền các tác vụ dựa trên mục tiêu sự kiện. Bạn có thể đã xem hoặc viết mã như dưới đây.
document.body.addEventListener('touchstart', event => {
if (event.target === area) {
event.preventDefault();
}
});
Vì bạn chỉ cần viết một trình xử lý sự kiện cho tất cả các phần tử, nên thông qua sự kiện này, bạn sẽ thấy mẫu uỷ quyền hấp dẫn. Tuy nhiên, nếu bạn xem mã này từ góc nhìn của trình duyệt chế độ xem, giờ đây, toàn bộ trang được đánh dấu là một khu vực không thể cuộn nhanh. Điều này có nghĩa là ngay cả khi ứng dụng không quan tâm đến dữ liệu đầu vào từ một số phần nhất định của trang, luồng của trình tổng hợp phải giao tiếp với luồng chính và chờ luồng đó mỗi khi có sự kiện đầu vào. Do đó, khả năng cuộn mượt mà của trình tổng hợp bị đánh bại.
Để giảm thiểu điều này, bạn có thể truyền các lựa chọn passive: true
vào sự kiện của mình
trình nghe. Điều này sẽ gợi ý cho trình duyệt biết rằng bạn vẫn muốn nghe sự kiện trong luồng chính,
nhưng trình tổng hợp cũng có thể tiếp tục và kết hợp khung mới.
document.body.addEventListener('touchstart', event => {
if (event.target === area) {
event.preventDefault()
}
}, {passive: true});
Kiểm tra xem sự kiện có thể huỷ hay không
Giả sử bạn có một hộp trong trang mà bạn muốn giới hạn hướng cuộn thành chỉ cuộn ngang.
Khi bạn sử dụng tuỳ chọn passive: true
trong sự kiện con trỏ, quá trình cuộn trang có thể mượt mà, nhưng
cuộn dọc có thể đã bắt đầu vào thời điểm bạn muốn preventDefault
để giới hạn
hướng cuộn. Bạn có thể kiểm tra lại bằng cách sử dụng phương thức event.cancelable
.
document.body.addEventListener('pointermove', event => {
if (event.cancelable) {
event.preventDefault(); // block the native scroll
/*
* do what you want the application to do here
*/
}
}, {passive: true});
Ngoài ra, bạn có thể sử dụng quy tắc CSS như touch-action
để loại bỏ hoàn toàn trình xử lý sự kiện.
#area {
touch-action: pan-x;
}
Tìm mục tiêu sự kiện
Khi luồng trình tổng hợp gửi một sự kiện đầu vào đến luồng chính, mục đầu tiên để chạy là một lượt truy cập thử nghiệm để tìm mục tiêu sự kiện. Kiểm tra lượt truy cập sử dụng dữ liệu bản ghi vẽ được tạo trong quá trình kết xuất để tìm ra nội dung bên dưới toạ độ điểm mà sự kiện đã xảy ra.
Giảm thiểu việc gửi sự kiện đến luồng chính
Trong bài đăng trước, chúng ta đã thảo luận về cách màn hình thông thường làm mới màn hình 60 lần mỗi giây và chúng tôi cần bắt kịp nhịp độ để hoạt ảnh mượt mà. Để nhập thông tin, màn hình cảm ứng thông thường thì thiết bị thực hiện thao tác chạm từ 60 đến 120 lần một giây và một con chuột thông thường thực hiện thao tác chạm 100 lần một giây. giây. Sự kiện đầu vào có độ trung thực cao hơn mức mà màn hình của chúng ta có thể làm mới.
Nếu một sự kiện liên tục như touchmove
được gửi đến luồng chính 120 lần/giây, thì sự kiện đó
có thể kích hoạt quá nhiều lần kiểm tra lần truy cập và thực thi JavaScript so với việc
màn hình có thể làm mới.
Để giảm thiểu số lệnh gọi quá nhiều đến luồng chính, Chrome sẽ tổng hợp các sự kiện liên tục (chẳng hạn như
wheel
, mousewheel
, mousemove
, pointermove
, touchmove
) và trì hoãn việc gửi hàng cho đến
ngay trước requestAnimationFrame
tiếp theo.
Mọi sự kiện rời rạc như keydown
, keyup
, mouseup
, mousedown
, touchstart
và touchend
được gửi đi ngay lập tức.
Sử dụng getCoalescedEvents
để nhận các sự kiện trong khung hình
Đối với hầu hết các ứng dụng web, các sự kiện được kết hợp là đủ để cung cấp trải nghiệm người dùng tốt.
Tuy nhiên, nếu bạn đang tạo những thứ như vẽ ứng dụng và đặt đường dẫn dựa trên
touchmove
toạ độ, bạn có thể bị mất các toạ độ ở giữa để vẽ một đường thẳng. Trong trường hợp đó,
bạn có thể dùng phương thức getCoalescedEvents
trong sự kiện con trỏ để lấy thông tin về
sự kiện được liên kết.
window.addEventListener('pointermove', event => {
const events = event.getCoalescedEvents();
for (let event of events) {
const x = event.pageX;
const y = event.pageY;
// draw a line using x and y coordinates.
}
});
Các bước tiếp theo
Trong loạt bài này, chúng tôi đã đề cập đến hoạt động bên trong trình duyệt web. Nếu bạn chưa từng nghĩ về lý do
Công cụ cho nhà phát triển đề xuất thêm {passive: true}
trên trình xử lý sự kiện hoặc lý do bạn có thể ghi async
trong thẻ tập lệnh của mình, tôi hy vọng loạt video này sẽ làm sáng tỏ lý do tại sao một trình duyệt cần những
để mang lại trải nghiệm web nhanh và mượt mà hơn.
Dùng Lighthouse
Nếu bạn muốn làm cho mã phù hợp với trình duyệt nhưng không biết bắt đầu từ đâu, Lighthouse là một công cụ chạy quy trình kiểm tra bất kỳ trang web nào và cung cấp cho bạn báo cáo về những nội dung cần cải thiện và những nội dung cần cải thiện. Đọc danh sách các cuộc kiểm tra cũng giúp bạn biết được những điều mà một trình duyệt quan tâm.
Tìm hiểu cách đo lường hiệu suất
Các nội dung điều chỉnh về hiệu suất có thể khác nhau tuỳ theo trang web, vì vậy, bạn cần phải đo lường hiệu suất của trang web rồi quyết định điều gì là phù hợp nhất với trang web của bạn. Nhóm Công cụ của Chrome cho nhà phát triển có một số hướng dẫn về cách đo lường hiệu suất của trang web.
Thêm Chính sách tính năng vào trang web
Nếu bạn muốn thực hiện thêm một bước, Chính sách tính năng là
nền tảng web có thể là rào chắn cho bạn khi xây dựng dự án. Đang bật
chính sách về tính năng đảm bảo một số hành vi nhất định của ứng dụng và giúp bạn không mắc sai lầm.
Ví dụ: Nếu muốn đảm bảo ứng dụng của mình sẽ không bao giờ chặn quá trình phân tích cú pháp, bạn có thể chạy ứng dụng trên
chính sách tập lệnh đồng bộ. Khi bạn bật sync-script: 'none'
, tính năng chặn trình phân tích cú pháp JavaScript sẽ
không được thực thi. Thao tác này ngăn mọi mã của bạn chặn trình phân tích cú pháp và
trình duyệt của bạn không cần phải lo lắng về việc tạm dừng trình phân tích cú pháp.
Tóm tắt
Khi bắt đầu xây dựng trang web, tôi hầu như chỉ quan tâm đến cách viết mã và những gì sẽ giúp tôi làm việc hiệu quả hơn. Những điều đó rất quan trọng, nhưng chúng ta cũng nên suy nghĩ về trình duyệt lấy mã chúng tôi viết. Các trình duyệt hiện đại đã và đang tiếp tục đầu tư vào cách mang lại trải nghiệm web tốt hơn cho người dùng. Đối xử tốt với trình duyệt bằng cách sắp xếp mã của chúng tôi, từ đó, cải thiện trải nghiệm người dùng. Tôi hy vọng bạn sẽ cùng tôi tham gia nhiệm vụ trở nên thân thiện với trình duyệt!
Rất cảm ơn những người đã đánh giá các bản nháp ban đầu của loạt video này, bao gồm (nhưng không giới hạn) đến): Alex Russell, Paul Ai-len, Meggin Kearney thân mến! Eric Bidelman, Mathias Bynens thân mến! Addy Osmani, Kinuko Yasuda, Nasko Oskov, và Charlie Reis.
Bạn có thích chuỗi video này không? Nếu bạn có câu hỏi hoặc đề xuất cho bài đăng trong tương lai, Tôi muốn nghe ý kiến của bạn trong phần bình luận bên dưới hoặc @kosamari trên Twitter.