Hiệu suất với cuộn vô hạn hoặc nhiều yếu tố dom?


77

Tôi có một câu hỏi về số lượng lớn dom elmenets và hiệu suất.

Giả sử tôi có 6000 phần tử dom trên một trang và số lượng phần tử có thể tăng lên khi người dùng tương tác với trang (người dùng cuộn để tạo một phần tử dom mới) như twitter.

Để cải thiện hiệu suất của trang, tôi chỉ có thể nghĩ đến hai điều.

  1. đặt hiển thị không hiển thị thành các mục ẩn để tránh chỉnh lại
  2. loại bỏ các mục vô hình khỏi dom sau đó thêm lại chúng nếu cần.

Chúng có bất kỳ cách nào khác để cải thiện một trang có nhiều yếu tố dom không?


3
Đặt hiển thị thành không kích hoạt chỉnh lại, điều này hoàn toàn trái ngược với những gì bạn muốn nếu những gì bạn muốn là tránh chỉnh lại. Không làm bất cứ điều gì không kích hoạt chỉnh lại. Đặt chế độ hiển thị thành ẩn cũng sẽ không kích hoạt chỉnh lại. Tuy nhiên, không làm bất cứ điều gì dễ dàng hơn nhiều.
slbetman,

3
Bạn cũng nên biết rằng trình quản lý cửa sổ của bạn đã xóa các pixel không nhìn thấy khỏi màn hình để tăng tốc độ tương tác với giao diện người dùng. Tự làm trong javascript có thể sẽ làm chậm mọi thứ thay vì tăng tốc.
slbetman

@slebetman // Khi tôi đặt hiển thị thành không, nó sẽ kích hoạt chỉnh lại. Đúng. nhưng..khi bạn cuộn, nó cũng kích hoạt chỉnh lại và trình duyệt phải tính toán bố cục cho tất cả các phần tử trên trang. Tôi nghĩ rằng cài đặt không hiển thị cho một số mục trên trang sẽ giúp giảm thời gian tính toán bố cục.
Mặt trăng

1
Không, không. Bạn có thể tự mình kiểm tra bằng cách biên dịch firefox hoặc chrome có bật gỡ lỗi và chạy nó thông qua một trình biên dịch. Thao tác cuộn kích hoạt sửa chữa, tất cả các thao tác cuộn trong tất cả các chương trình, thậm chí Word hoặc Notepad kích hoạt sửa chữa. Ngay cả khi di chuyển con trỏ chuột cũng kích hoạt sửa chữa. Nhưng giá sửa lại rẻ - chúng đã được tối ưu hóa từ cuối những năm 1980 và được thực hiện bởi chính trình quản lý hệ điều hành / cửa sổ chứ không phải chương trình. Thao tác cuộn không kích hoạt chỉnh lại.
slbetman

1
@slebetman // ah..Tôi có ấn tượng về chỉnh sửa cuộn từ video paulirish.com/2011/dom-html5-css3-performance . Video liệt kê window.scrollBy gây ra chỉnh lại. Tôi tự hỏi tại sao nó lại có khi cuộn của người dùng thì không.
Mặt trăng

Câu trả lời:


26

Bản thân tôi không có kinh nghiệm về điều này, nhưng có một số mẹo tuyệt vời ở đây: http://engineering.linkedin.com/linkedin-ipad-5-techniques-smooth-infinite-scrolling-html5

Tôi đã xem qua Facebook và họ dường như không làm được gì cụ thể trên Firefox. Khi bạn cuộn xuống, các phần tử DOM ở đầu trang không thay đổi. Mức sử dụng bộ nhớ của Firefox tăng lên khoảng 500 meg trước khi Facebook không cho phép bạn cuộn thêm.

Twitter dường như giống với Facebook.

Google Maps là một câu chuyện khác - các ô bản đồ nằm ngoài tầm nhìn sẽ bị xóa khỏi DOM (mặc dù không phải ngay lập tức).


1
// Cảm ơn bạn đã dành thời gian điều tra kết quả của mình. Tôi sẽ làm như vậy sớm.
Mặt trăng

2
Sẽ thực sự thú vị khi xem Pinterest làm điều đó như thế nào. Họ dường như đã tìm ra điều đó khi họ tải động các phần tử khi bạn cuộn xuống và sao lưu. Họ dường như luôn có một số lượng Ghim được đặt trên trang nguồn cấp dữ liệu tại bất kỳ thời điểm nào.
alex

103

Chúng tôi đã phải giải quyết một vấn đề tương tự trên FoldingText . Khi tài liệu lớn hơn, nhiều phần tử đường và phần tử nhịp liên quan được tạo ra. Bộ máy của trình duyệt dường như bị nghẹt và vì vậy cần phải tìm ra giải pháp tốt hơn.

Đây là những gì chúng tôi đã làm, có thể hữu ích hoặc không cho mục đích của bạn:

Hình dung toàn bộ trang dưới dạng một tài liệu dài và khung nhìn của trình duyệt như ống kính cho một phần cụ thể của tài liệu dài. Bạn thực sự chỉ phải hiển thị phần bên trong ống kính.

Vì vậy, phần đầu tiên là tính toán cổng nhìn thấy được. (Điều này phụ thuộc vào cách các phần tử của bạn được đặt, tuyệt đối / cố định / mặc định)

var top = document.scrollTop;
var width = window.innerWidth;
var height = window.innerHeight;

Một số tài nguyên khác để tìm một chế độ xem dựa trên nhiều trình duyệt hơn:

Nhận kích thước khung nhìn của trình duyệt với JavaScript

Phương pháp trình duyệt chéo để phát hiện scrollTop của cửa sổ trình duyệt

Thứ hai, bạn cần một cấu trúc dữ liệu để biết những phần tử nào có thể nhìn thấy trong khu vực đó

Chúng tôi đã có sẵn một cây tìm kiếm nhị phân cân bằng để chỉnh sửa văn bản, vì vậy chúng tôi cũng mở rộng nó để quản lý chiều cao dòng, vì vậy phần này đối với chúng tôi tương đối dễ dàng. Tôi không nghĩ rằng bạn sẽ cần một cấu trúc dữ liệu phức tạp để quản lý chiều cao phần tử của mình; một mảng hoặc đối tượng đơn giản có thể hoạt động tốt. Chỉ cần đảm bảo rằng bạn có thể truy vấn chiều cao và kích thước dễ dàng trên đó. Bây giờ, bạn sẽ lấy dữ liệu chiều cao cho tất cả các phần tử của mình như thế nào. Rất đơn giản (nhưng tốn kém về mặt tính toán đối với số lượng lớn các phần tử!)

var boundingRect = element.getBoundingClientRect()

Tôi đang nói về javascript tinh khiết, nhưng nếu bạn đang sử dụng jQuery $.offset, $.positionvà các phương pháp được liệt kê ở đây sẽ khá hữu ích.

Một lần nữa, việc sử dụng cấu trúc dữ liệu chỉ quan trọng như một bộ nhớ cache, nhưng nếu bạn muốn, bạn có thể thực hiện nó ngay lập tức (mặc dù như tôi đã nói những thao tác này rất tốn kém). Ngoài ra, hãy cẩn thận khi thay đổi kiểu css và gọi các phương thức này. Các hàm này buộc phải vẽ lại, vì vậy bạn sẽ thấy vấn đề về hiệu suất.

Cuối cùng, chỉ cần thay thế các phần tử ngoài màn hình bằng một <div>phần tử duy nhất có chiều cao được tính toán

  • Bây giờ, bạn có chiều cao cho tất cả các phần tử được lưu trữ trong cấu trúc Dữ liệu của mình, hãy truy vấn tất cả các phần tử nằm trước khung nhìn hiển thị.

  • Tạo một <div>với chiều cao css được đặt (tính bằng pixel) thành tổng chiều cao của phần tử

  • Đánh dấu nó bằng tên lớp để bạn biết nó là div phụ
  • Xóa tất cả các phần tử khỏi dom mà div này bao gồm
  • chèn div mới tạo này thay thế

Lặp lại các phần tử nằm sau khung nhìn hiển thị.

Tìm kiếm các sự kiện cuộn và thay đổi kích thước. Trên mỗi cuộn, bạn sẽ cần quay lại cấu trúc dữ liệu của mình, xóa các div phụ, tạo các phần tử trước đó đã bị xóa khỏi màn hình và theo đó thêm các div phụ mới.

:) Đó là một phương pháp dài và phức tạp, nhưng đối với các tài liệu lớn, nó đã làm tăng hiệu suất của chúng tôi lên một mức lớn.

tl; dr

Tôi không chắc mình đã giải thích nó đúng cách, nhưng ý chính của phương pháp này là:

  • Biết kích thước dọc của các phần tử của bạn
  • Biết cổng chế độ xem được cuộn
  • Biểu diễn tất cả các phần tử ngoài màn hình bằng một div duy nhất (chiều cao bằng tổng tất cả các chiều cao phần tử mà nó bao gồm)
  • Bạn sẽ cần tổng cộng hai div tại bất kỳ thời điểm nhất định nào, một cho các phần tử phía trên khung nhìn hiển thị, một cho các phần tử bên dưới.
  • Theo dõi cổng xem bằng cách lắng nghe các sự kiện cuộn và thay đổi kích thước. Tạo lại các div và các phần tử hiển thị cho phù hợp

Hi vọng điêu nay co ich.


// Điều đó có lý! Cảm ơn bạn đã hiểu biết của bạn!
Mặt trăng

Bạn có thể đưa ra một ví dụ về trường hợp cần cấu trúc dữ liệu phức tạp không?
Joren Van Severen

3
Btw, tôi thấy đây là cách duy nhất để xử lý nhiều phần tử DOM mà vẫn có trải nghiệm cuộn hợp lý. Ngoài ra, việc tìm nạp trình xử lý cuộn scrollTop trong (jquery) không gây ra vẽ lại. Trên thực tế, nó không bao giờ làm như vậy, nó chỉ xóa hàng đợi vẽ lại và sửa lại để có thể trả lại scrollTop cập nhật cuối cùng. Tôi đoán rằng nó đã được cập nhật vào thời điểm xử lý sổ sách.
Joren Van Severen

1
@JorenVanSeveren Nó phụ thuộc vào nhu cầu của bạn về cấu trúc dữ liệu phức tạp. Như tôi đã nói, chúng tôi sử dụng cây nhị phân cân bằng vì chúng tôi đã có sẵn một cây. Tôi không nghĩ bạn sẽ cần nó để CHỈ quản lý độ cao của dom.
Mutahhir,

8
@Moon: Kỹ thuật tương tự được nêu trong câu trả lời này đã được triển khai dưới dạng một plugin. ClusterizeJS . Hoạt động chính xác như mong đợi và nó cũng hỗ trợ tính ngang giá vật phẩm nếu bạn cần. Và nó thực sự hoạt động tuyệt vời! (FYI: Tôi không phải là nhà phát triển của nó)
Robert Koritnik

9

Đó là năm 2019. Câu hỏi này thực sự đã cũ, nhưng tôi nghĩ nó vẫn còn phù hợp và thú vị và có thể một điều gì đó đã thay đổi cho đến ngày hôm nay, vì tất cả chúng ta bây giờ cũng có xu hướng sử dụng React JS.

Tôi nhận thấy rằng dòng thời gian của Facebook dường như sử dụng các cụm nội dung bị ẩn display: none !importantngay sau khi cụm đó không xem được, vì vậy tất cả các phần tử được hiển thị trước đó của DOM được giữ trong DOM, chỉ là những phần tử nằm ngoài tầm nhìn được ẩn với display: none !important. Ngoài ra, chiều cao tổng thể của cụm ẩn được đặt thành mẹ divcủa cụm ẩn.

Đây là một số ảnh chụp màn hình tôi đã thực hiện:

nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây

Vào năm 2019, bạn nghĩ gì về cách tiếp cận này? Ngoài ra, đối với những người sử dụng React, làm thế nào nó có thể được triển khai trong React? Sẽ thật tuyệt nếu nhận được ý kiến ​​và suy nghĩ của bạn về chủ đề khó nhằn này.

Cám ơn sự chú ý của các bạn!

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.