Это смесь бесконечной таблицы и бесконечной прокрутки. Лучшая абстракция, которую я нашел для этого, следующая:
Обзор
Создайте <List>
компонент, который принимает массив всех дочерних элементов . Поскольку мы не обрабатываем их, очень дешево просто выделить их и отбросить. Если выделения 10k слишком велики, вы можете вместо этого передать функцию, которая принимает диапазон и возвращает элементы.
<List>
{thousandelements.map(function() { return <Element /> })}
</List>
Ваш List
компонент отслеживает позицию прокрутки и отображает только дочерние элементы, которые находятся в поле зрения. Он добавляет большой пустой div в начале, чтобы подделать предыдущие элементы, которые не отображаются.
Теперь самое интересное то, что после Element
рендеринга компонента вы измеряете его высоту и сохраняете в своем List
. Это позволяет вычислить высоту разделителя и узнать, сколько элементов должно отображаться в поле зрения.
Образ
Вы говорите, что при загрузке изображения они заставляют все "прыгать" вниз. Решение этого заключается в том, чтобы установить размеры изображения в вашей IMG тег: <img src="..." width="100" height="58" />
. Таким образом, браузеру не нужно ждать, чтобы загрузить его, прежде чем он узнает, какой размер он будет отображаться. Для этого требуется некоторая инфраструктура, но оно того стоит.
Если вы не можете заранее узнать размер, то добавьте onload
слушателей к своему изображению, и когда оно будет загружено, измерьте его отображаемый размер, обновите сохраненную высоту строки и скомпенсируйте положение прокрутки.
Прыжки на случайный элемент
Если вам нужно перейти к случайному элементу в списке, это потребует некоторых хитростей с позицией прокрутки, потому что вы не знаете размер элементов между ними. Я предлагаю вам усреднить высоту элементов, которую вы уже вычислили, и перейти к положению прокрутки последней известной высоты + (количество элементов * среднее).
Поскольку это не совсем точно, это вызовет проблемы, когда вы вернетесь к последней удачной позиции. Когда возникает конфликт, просто измените положение прокрутки, чтобы исправить его. Это немного сдвинет полосу прокрутки, но не должно сильно повлиять на него / нее.
Особенности реакции
Вы хотите предоставить ключ ко всем визуализируемым элементам, чтобы они сохранялись во время визуализации. Есть две стратегии: (1) иметь только n ключей (0, 1, 2, ... n), где n - максимальное количество элементов, которые вы можете отобразить, и использовать их положение по модулю n. (2) иметь разные ключи для каждого элемента. Если все элементы имеют аналогичную структуру, хорошо использовать (1) для повторного использования их узлов DOM. Если нет, используйте (2).
У меня было бы только две части состояния React: индекс первого элемента и количество отображаемых элементов. Текущая позиция прокрутки и высота всех элементов будут напрямую прикреплены к this
. Когда используешьsetState
вы фактически выполняете повторную визуализацию, которая должна происходить только при изменении диапазона.
Вот пример бесконечного списка с использованием некоторых методов, которые я описываю в этом ответе. Это будет некоторая работа, но React определенно хороший способ реализовать бесконечный список :)