Вистава з нескінченною прокруткою або великою кількістю елементів дому?


77

У мене запитання щодо великої кількості домашніх ельменетів та продуктивності.

Скажімо, у мене на сторінці 6000 елементів dom, і кількість елементів можна збільшити, коли користувач взаємодіє зі сторінкою (користувач прокручує сторінку, щоб створити новий елемент dom), як твіттер.

Для підвищення продуктивності сторінки я можу думати лише про дві речі.

  1. встановіть для дисплея значення none для невидимих ​​елементів, щоб уникнути переформатування
  2. видаліть невидимі предмети з купола, а потім додайте їх за потреби.

Чи є вони якимись іншими способами вдосконалення сторінки з великою кількістю елементів dom?


3
Якщо встановити значення дисплея на жодне, не запускається перекомпонування, яке повністю протилежне тому, що ви хочете, якщо те, що ви хочете, це уникати переформатування. Якщо нічого не робити, це не викликає перепланування. Якщо встановити видимість як приховану, це також не спричинить переформатування. Однак не робити нічого набагато простіше.
slebetman

3
Також слід пам’ятати, що менеджер вікон вже видаляє невидимі пікселі з екрана, щоб пришвидшити взаємодію з користувацьким інтерфейсом. Якщо зробити це самостійно у javascript, швидше за все, це сповільниться, а не прискориться.
slebetman

@slebetman // Коли я встановлюю display на none, це спрацьовує reflow. Це правда. але ... коли ви прокручуєте, це також запускає переформатування, і браузер повинен розрахувати макет для всіх елементів на сторінці. Я думав, що налаштування не відображати деякі елементи на сторінці допоможе скоротити час розрахунку макета.
Місяць

1
Ні, це не так. Ви можете перевірити це самостійно, скомпілювавши firefox або chrome із налагодженою функцією та провівши через профайлер. Прокрутка запускає перефарбовування, вся прокрутка у всіх програмах, навіть Word або Блокнот, запускає перефарбовування. Навіть переміщення вказівника миші викликає перефарбування. Але перефарбовування коштує дешево - вони вже оптимізовані з кінця 1980-х років і реалізуються самим менеджером ОС / вікон, а не програмою. Прокрутка не викликає переформатування.
slebetman

1
@slebetman // ах..У мене склалося враження про перегляд прокрутки з відео paulirish.com/2011/dom-html5-css3-performance . У відеозаписі вказано, що window.scrollBy викликає перекомпонування. Цікаво, чому це відбувається, коли прокрутка користувача цього не робить.
Місяць

Відповіді:


26

Я не маю досвіду з цим, але тут є кілька чудових порад: http://engineering.linkedin.com/linkedin-ipad-5-techniques-smooth-infinite-scrolling-html5

Я подивився Facebook, і вони, здається, нічого особливо не роблять у Firefox. Під час прокрутки вниз елементи DOM у верхній частині сторінки не змінюються. Використання пам'яті Firefox зростає приблизно до 500 мегабайт, перш ніж Facebook не дозволить прокручувати далі.

Twitter, схоже, такий самий, як і Facebook.

Карти Google - це зовсім інша історія - плитки карт, які не видно з поля зору, видаляються з DOM (хоча і не відразу).


1
// Дякуємо, що знайшли час, щоб дослідити свою знахідку. Незабаром я зроблю те саме.
Місяць

2
Було б дуже цікаво подивитися, як це робить Pinterest. Здається, вони це зрозуміли, завантажуючи елементи динамічно, коли ви прокручуєте вниз і назад. Здається, вони завжди мають задану кількість контактів, завантажених на сторінку стрічки в будь-який момент часу.
alex

103

Нам довелося мати справу з подібною проблемою на FoldingText . У міру того як документ збільшувався, створювалося більше елементів рядка та пов'язаних з ним елементів прольоту. Здавалося, двигун браузера просто задихнувся, і тому потрібно було знайти краще рішення.

Ось що ми зробили, може бути, а може не бути корисним для ваших цілей:

Візуалізуйте всю сторінку як довгий документ, а область перегляду браузера як об’єктив для певної частини довгого документа. Насправді вам потрібно лише показати ту частину в об’єктиві.

Отже, перша частина - це обчислення порту видимого перегляду. (Це залежить від розміщення елементів, абсолютного / фіксованого / за замовчуванням)

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

Дещо більше ресурсів, щоб знайти більше вікна перегляду на основі браузера:

Отримайте розміри області перегляду браузера за допомогою JavaScript

Метод перехресного перегляду для виявлення прокрутки доверху вікна браузера

По-друге, вам потрібна структура даних, щоб знати, які елементи видно в цій області

У нас вже було збалансоване двійкове дерево пошуку для редагування тексту, тому ми також розширили його для управління висотами рядків, тому ця частина для нас була відносно простою. Я не думаю, що вам знадобиться складна структура даних для управління висотами елементів; простий масив або об'єкт може добре справитись. Просто переконайтеся, що ви можете легко запитувати висоту та розміри на ньому. Тепер, як би ви отримали дані про висоту для всіх ваших елементів. Дуже простий (але обчислювально дорогий для великої кількості елементів!)

var boundingRect = element.getBoundingClientRect()

Я говорю з точки зору чистого JavaScript, але якщо ви використовуєте JQuery $.offset, $.positionі методи , перераховані тут , було б дуже корисним.

Знову ж таки, використання структури даних важливо лише як кеш, але якщо ви хочете, ви можете зробити це на льоту (хоча, як я вже зазначав, ці операції є дорогими). Крім того, остерігайтеся зміни стилів css та виклику цих методів. Ці функції змушують перемальовувати, тому ви побачите проблему з продуктивністю.

Нарешті, просто замініть елементи поза екраном на один, скажімо, <div>елемент із розрахунковою висотою

  • Тепер у вас є висоти для всіх елементів, що зберігаються у вашій структурі даних, запитуйте всі елементи, які лежать перед видимим вікном перегляду.

  • Створіть <div>з набором висоти css (у пікселях) суму висот елементів

  • Позначте його назвою класу, щоб ви знали його заповнювач div
  • Видаліть усі елементи з купола, який охоплює цей div
  • вставити замість цього щойно створений div

Повторіть для елементів, які лежать після видимого вікна перегляду.

Шукайте події прокрутки та зміни розміру. На кожному прокручуванні вам потрібно буде повернутися до структури даних, видалити заповнювачі div, створити елементи, які раніше були видалені з екрана, і відповідно додати нові div заповнювача.

:) Це довгий, складний метод, але для великих документів він значно збільшив наші показники.

tl; д-р

Я не впевнений, що я це правильно пояснив, але суть цього методу:

  • Знайте вертикальні розміри ваших елементів
  • Знати порт прокрутки подання
  • Представляти всі позаекранні елементи за допомогою одного div (висота, що дорівнює сумі всіх висот елементів, які вона охоплює)
  • У будь-який момент вам знадобляться два div, загалом, один для елементів над видимим вікном перегляду, другий для елементів нижче.
  • Відстежуйте порт перегляду, слухаючи події прокрутки та зміни розміру. Відтворіть відповідно div та видимі елементи

Сподіваюся, це допомагає.


// Що має сенс! Дякуємо за розуміння!
Місяць

Чи можете ви навести приклад випадку, коли була б потрібна складна структура даних?
Йорен Ван Северен

3
До речі, я виявив, що це єдиний спосіб обробити велику кількість елементів DOM з досі розумним досвідом прокрутки. Крім того, отримання scrollTop у (jquery) обробнику прокрутки не викликає перемальовування. Насправді цього ніколи не відбувається, він лише очищає чергу перемальовувань та перефарбовувань, щоб можна було повернути останню актуальну scrollTop. Я припускаю, що це вже оновлено на той момент, коли обробляється прокрутка.
Йорен Ван Северен

1
@JorenVanSeveren Це залежить від ваших потреб re: складні структури даних. Як я вже говорив, ми використовували збалансоване двійкове дерево, оскільки воно вже було на місці. Я не думаю, що він вам знадобиться для ПРОСТОГО управління висотами купола.
Мутахір

8
@Moon: Цей самий прийом, викладений у цій відповіді, був реалізований у формі плагіна. Кластеризувати JS . Працює точно так, як очікувалося, а також підтримує паритет елементів, якщо він вам потрібен. І це справді чудово працює! (FYI: Я не його розробник)
Роберт Коритник,

9

Це 2019 рік. Питання справді давнє, але я думаю, що воно все ще актуальне та цікаве, і, можливо, щось змінилося на сьогодні, оскільки всі ми зараз також використовуємо React JS.

Я помітив, що часова шкала Facebook, здається, використовує скупчення вмісту, який приховано display: none !important як тільки кластер виходить з поля зору, тому всі попередньо відтворені елементи DOM зберігаються в DOM, просто ті, що не входять в поле зору, приховані за допомогою display: none !important. Крім того, загальна висота прихованого кластера встановлюється батьківським divприхованим кластером.

Ось кілька знімків екрану, які я зробив:

введіть тут опис зображення

введіть тут опис зображення

введіть тут опис зображення

Станом на 2019 рік, що ви думаєте про цей підхід? Крім того, для тих, хто використовує React, як його можна реалізувати в React? Було б чудово отримати ваші думки та думки щодо цієї хитромудрої теми.

Дякую за увагу!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.