IntersectionObserver sẽ xuất hiện

IntersectionObservers cho bạn biết khi nào một phần tử được quan sát đi vào hoặc thoát khỏi khung nhìn của trình duyệt.

Hỗ trợ trình duyệt

  • 51
  • 15
  • 55
  • 12,1

Nguồn

Giả sử bạn muốn theo dõi thời điểm một phần tử trong DOM chuyển sang khung nhìn hiển thị. Bạn có thể cần làm như vậy để có thể tải từng phần hình ảnh vừa kịp thời hoặc vì bạn cần biết liệu người dùng có thực sự đang xem một biểu ngữ quảng cáo nhất định hay không. Bạn có thể làm việc này bằng cách kết nối sự kiện cuộn hoặc sử dụng bộ tính giờ định kỳ rồi gọi getBoundingClientRect() trên phần tử đó.

Tuy nhiên, phương pháp này rất chậm vì mỗi lệnh gọi đến getBoundingClientRect() sẽ buộc trình duyệt bố cục lại toàn bộ trang và sẽ khiến trang web của bạn bị giật đáng kể. Các vấn đề gần như không thể xảy ra khi bạn biết trang web của mình đang được tải bên trong iframe và bạn muốn biết khi nào người dùng có thể thấy một phần tử. Mô hình nguồn gốc duy nhất và trình duyệt sẽ không cho phép bạn truy cập vào bất kỳ dữ liệu nào từ trang web chứa iframe. Đây là một vấn đề phổ biến đối với quảng cáo, chẳng hạn như quảng cáo thường xuyên được tải bằng iframe.

Việc IntersectionObserver được thiết kế nhằm mục đích cải thiện khả năng hiển thị và đã có mặt trong tất cả trình duyệt hiện đại. IntersectionObserver cho bạn biết khi một phần tử được quan sát đi vào hoặc thoát khỏi khung nhìn của trình duyệt.

Chế độ hiển thị iframe

Cách tạo IntersectionObserver

API này khá nhỏ và được mô tả tốt nhất bằng cách sử dụng ví dụ:

const io = new IntersectionObserver(entries => {
  console.log(entries);
}, {
  /* Using default options. Details below */
});

// Start observing an element
io.observe(element);

// Stop observing an element
// io.unobserve(element);

// Disable entire IntersectionObserver
// io.disconnect();

Khi sử dụng các tuỳ chọn mặc định cho IntersectionObserver, lệnh gọi lại của bạn sẽ được gọi cả khi phần tử xuất hiện một phần vào khung nhìn và khi phần tử đó rời khỏi khung nhìn hoàn toàn.

Nếu cần quan sát nhiều phần tử, thì bạn có thể và bạn nên quan sát nhiều phần tử bằng cách sử dụng cùng một thực thể IntersectionObserver bằng cách gọi observe() nhiều lần.

Tham số entries được truyền đến lệnh gọi lại. Đây là một mảng các đối tượng IntersectionObserverEntry. Mỗi đối tượng như vậy chứa dữ liệu nút giao đã cập nhật cho một trong các yếu tố được quan sát của bạn.

🔽[IntersectionObserverEntry]
    time: 3893.92
    🔽rootBounds: ClientRect
        bottom: 920
        height: 1024
        left: 0
        right: 1024
        top: 0
        width: 920
    🔽boundingClientRect: ClientRect
    // ...
    🔽intersectionRect: ClientRect
    // ...
    intersectionRatio: 0.54
    🔽target: div#observee
    // ...

rootBounds là kết quả của việc gọi getBoundingClientRect() trên thành phần gốc, là khung nhìn theo mặc định. boundingClientRect là kết quả của getBoundingClientRect() được gọi trên phần tử được quan sát. intersectionRect là giao điểm của hai hình chữ nhật này và cho bạn biết phần nào của phần tử được quan sát sẽ hiển thị. intersectionRatio có liên quan chặt chẽ và cho bạn biết mức hiển thị của phần tử. Với thông tin này, bạn hiện có thể triển khai các tính năng như tải thành phần đúng lúc trước khi chúng xuất hiện trên màn hình. Hiệu quả.

Tỷ lệ giao lộ.

IntersectionObserver phân phối dữ liệu không đồng bộ và mã gọi lại của bạn sẽ chạy trong luồng chính. Ngoài ra, thông số kỹ thuật thực sự cho biết rằng các quá trình triển khai IntersectionObserver nên sử dụng requestIdleCallback(). Điều này có nghĩa là lệnh gọi đến lệnh gọi lại mà bạn cung cấp có mức độ ưu tiên thấp và sẽ được trình duyệt thực hiện trong thời gian không hoạt động. Đây là một quyết định thiết kế sáng suốt.

Div cuộn

Tôi không thích việc cuộn bên trong một phần tử, nhưng tôi không muốn đánh giá và IntersectionObserver cũng vậy. Đối tượng options có tuỳ chọn root cho phép bạn xác định một phương án thay thế cho khung nhìn làm gốc. Điều quan trọng cần lưu ý là root cần phải là đối tượng cấp trên của tất cả các phần tử được quan sát.

Giao thoa mọi thứ!

Không đâu! Nhà phát triển rất tệ! Thao tác này không chú ý đến việc sử dụng chu kỳ CPU của người dùng. Hãy cùng xem một ví dụ về trình cuộn vô hạn: Trong trường hợp đó, bạn nên thêm sentinels vào DOM, đồng thời quan sát (và tái chế!) những công cụ đó. Bạn nên thêm một người canh gác gần mục cuối cùng trong thanh cuộn vô hạn. Khi trọng điểm đó xuất hiện, bạn có thể sử dụng lệnh gọi lại để tải dữ liệu, tạo các mục tiếp theo, đính kèm chúng vào DOM và định vị lại giám sát cho phù hợp. Nếu tái chế trọng điểm đúng cách, thì bạn không cần gọi thêm đến observe(). IntersectionObserver vẫn tiếp tục hoạt động.

Thanh cuộn vô hạn

Vui lòng cung cấp thêm thông tin cập nhật

Như đã đề cập trước đó, lệnh gọi lại sẽ được kích hoạt vào một lần khi phần tử được quan sát xuất hiện một phần vào khung nhìn và một lần khác khi phần tử đó rời khỏi khung nhìn. Bằng cách này, IntersectionObserver sẽ trả lời cho bạn câu hỏi "Phần tử X có đang hiển thị không?". Tuy nhiên, trong một số trường hợp sử dụng, như vậy là chưa đủ.

Đây là lúc tuỳ chọn threshold phát huy tác dụng. Phương thức này cho phép bạn xác định một mảng ngưỡng intersectionRatio. Lệnh gọi lại của bạn sẽ được gọi mỗi khi intersectionRatio vượt qua một trong các giá trị này. Giá trị mặc định của threshold[0], giải thích hành vi mặc định. Nếu thay đổi threshold thành [0, 0.25, 0.5, 0.75, 1], chúng ta sẽ nhận được thông báo mỗi khi thêm một phần tư của phần tử hiển thị:

Ảnh động ngưỡng.

Bạn có lựa chọn nào khác không?

Hiện tại, bạn chỉ còn một lựa chọn khác ngoài những lựa chọn nêu trên. rootMargin cho phép bạn chỉ định lề cho gốc, cho phép bạn mở rộng hoặc thu nhỏ diện tích dùng cho các giao lộ một cách hiệu quả. Các lề này được chỉ định bằng một chuỗi kiểu CSS, á la "10px 20px 30px 40px", xác định lề trên, phải, dưới và trái tương ứng. Tóm lại, cấu trúc tuỳ chọn IntersectionObserver cung cấp các tuỳ chọn sau:

new IntersectionObserver(entries => {/* … */}, {
  // The root to use for intersection.
  // If not provided, use the top-level document's viewport.
  root: null,
  // Same as margin, can be 1, 2, 3 or 4 components, possibly negative lengths.
  // If an explicit root element is specified, components may be percentages of the
  // root element size.  If no explicit root element is specified, using a
  // percentage is an error.
  rootMargin: "0px",
  // Threshold(s) at which to trigger callback, specified as a ratio, or list of
  // ratios, of (visible area / total area) of the observed element (hence all
  // entries must be in the range [0, 1]).  Callback will be invoked when the
  // visible ratio of the observed element crosses a threshold in the list.
  threshold: [0],
});

<iframe> phép thuật

IntersectionObserver được thiết kế riêng cho các dịch vụ quảng cáo và tiện ích con trên mạng xã hội. Các tiện ích này thường sử dụng phần tử <iframe> và có thể hưởng lợi khi biết liệu các phần tử này có hiển thị trong khung hiển thị hay không. Nếu <iframe> quan sát thấy một trong các phần tử của nó, thì cả thao tác cuộn <iframe> cũng như cuộn cửa sổ chứa <iframe> đều sẽ kích hoạt lệnh gọi lại vào những thời điểm thích hợp. Tuy nhiên, trong trường hợp sau, rootBounds sẽ được đặt thành null để tránh rò rỉ dữ liệu giữa các nguồn gốc.

IntersectionObserver Không nói về điều gì?

Một điểm cần lưu ý là IntersectionObserver không cố ý là điểm ảnh hoàn hảo hay có độ trễ thấp. Việc sử dụng chúng để triển khai các hoạt động như ảnh động phụ thuộc vào thao tác cuộn chắc chắn sẽ không thành công, vì dữ liệu (nói nghiêm ngặt hơn) sẽ bị lỗi thời vào thời điểm bạn sử dụng. Nội dung giải thích có thêm thông tin chi tiết về các trường hợp sử dụng ban đầu của IntersectionObserver.

Tôi có thể làm bao nhiêu việc trong lệnh gọi lại?

Ngắn gọn: Việc dành quá nhiều thời gian cho lệnh gọi lại sẽ khiến ứng dụng chạy chậm hơn. Tất cả các phương pháp phổ biến đều áp dụng.

Đi tới và giao với các thành phần của bạn

Trình duyệt hỗ trợ IntersectionObserver rất tốt, vì trình duyệt này có sẵn trong tất cả các trình duyệt hiện đại. Nếu cần, bạn có thể sử dụng polyfill trong các trình duyệt cũ và có sẵn trong kho lưu trữ của WICG. Rõ ràng, bạn sẽ không nhận được các lợi ích về hiệu suất khi sử dụng polyfill đó mà phương thức triển khai gốc sẽ mang lại cho bạn.

Bạn có thể bắt đầu sử dụng IntersectionObserver ngay bây giờ! Hãy cho chúng tôi biết ý kiến của bạn.