Войти Регистрация
Фронтенд

36. Виртуальная лента VK с постами разной высоты

Средняя

В ленте VK посты разной высоты: текст на две строки — 80 px, пост с фото — 300, с опросом — 200. За вечер пользователь пролистывает 2–3 тысячи постов, и рендерить их все нельзя. Высоту каждого поста лента знает после замера.

Напишите createVirtualList(heights) — объект с двумя методами. range(scrollTop, viewportHeight, overscan) возвращает { start, end, offset, total }: строки start ≤ i < end рендерим, offset — верх строки start, total — высота всего списка.

Строка i занимает отрезок [top_i, top_i + h_i). Видимая — та, что пересекается с окном [scrollTop, scrollTop + viewportHeight): строка, которая начинается ровно на нижней границе окна, не видна. К видимым добавьте overscan строк сверху и снизу. scrollTop ограничьте отрезком [0, max(0, total − viewportHeight)].

setHeight(i, h) меняет высоту строки после замера — следующий range учитывает её. Высоты положительные, пустой список даёт нули.

В работе: Ленты и чаты с элементами разной высоты, таблицы с раскрывающимися строками.

Пример 1: верх ленты

Аргументы теста
[120, 80, 300, 60, 60, 200, 100], [["range", 0, 250, 0]]
Ожидается
[{"start": 0, "end": 3, "offset": 0, "total": 920}]

Пример 2: окно внутри одного поста

Аргументы теста
[120, 80, 300, 60, 60, 200, 100], [["range", 210, 150, 0]]
Ожидается
[{"start": 2, "end": 3, "offset": 200, "total": 920}]
Как проверяем Объявите createVirtualList — тест вызывает её сам. Таймеры и Date в тестах ненастоящие: время идёт по команде теста, поэтому setTimeout на 5 секунд проверяется мгновенно. Тестов 10: 2 открыты выше, остальные приходят после старта подхода. Лимит — 2 с на тест.
function createVirtualList(heights) // → { range(scrollTop, viewportHeight, overscan), setHeight(i, h) }
виртуализацияпрефиксные суммыбинарный поиск

Источник: на задачах VK: лента новостей. Условие пересказано своими словами.