Нескінченна стрічка
Стрічка, що ніколи не закінчується, мусить завантажувати дані, поки глядач дивиться: досить рано, щоб наступний допис уже був на місці, з чимось на екрані, поки сторінка в дорозі чи не завантажилася, і без запиту, що лишився працювати після того, як стрічки вже немає.
Спробуйте
Кожна версія імпортує ./api, що заміняє ваш бекенд: fetchPosts(page, signal) повертає одну сторінку дописів і зупиняється, коли сигнал скасовано. Замініть його викликом вашого API й приберіть failNextRequest, який лише керує перемикачем збою в демо.
import { createSignal } from '@reelkit/core';
import { cdnUrl } from '@reelkit/example-data';
// Stands in for your backend. The recipe only relies on the signature of
// `fetchPosts`: a page number in, a page of posts out, cancellable through an
// AbortSignal.
export interface Post {
id: string;
title: string;
image: string;
}
const kPageSize = 6;
const kDelayMs = 800;
const kImages = Array.from(
{ length: 9 },
(_, i) => `samples/images/image-${String(i + 1).padStart(2, '0')}.jpg`,
);
/**
* Demo switch: while on, the next request fails, so the error slide can be
* seen. A signal, so the switch shows when a request has used it up. Only the
* demo on this page uses it: delete it, and the `@reelkit/core` import with
* it, when you replace `fetchPosts` with your API.
*/
export const failNextRequest = createSignal(false);
export function fetchPosts(page: number, signal: AbortSignal): Promise<Post[]> {
return new Promise((resolve, reject) => {
const timer = setTimeout(() => {
if (failNextRequest.value) {
failNextRequest.value = false;
reject(new Error('The feed could not be loaded.'));
return;
}
resolve(
Array.from({ length: kPageSize }, (_, i) => {
const n = page * kPageSize + i;
return {
id: `post-${n}`,
title: `Post ${n + 1}`,
image: cdnUrl(kImages[n % kImages.length]),
};
}),
);
}, kDelayMs);
signal.addEventListener(
'abort',
() => {
clearTimeout(timer);
reject(signal.reason);
},
{ once: true },
);
});
}Зразкові медіа працюють лише на reelkit.dev
cdnUrl будує посилання на cdn.reelkit.dev, який віддає файли лише сайтам ReelKit. У вашому застосунку ці зображення не завантажаться, тож перш ніж копіювати цей файл, спрямуйте image на власні медіа.
Гортайте вгору або натисніть ↓: нова сторінка надходить за три дописи до кінця. Натисніть «Fail next request», щоб побачити слайд помилки та його кнопку Retry.
Чому це працює
- Кількість росте, слайдів не більшає.
count— це кількість дописів плюс один, а в DOM завжди лише три слайди, тож стрічка з т исяч дописів коштує стільки ж, скільки з десяти. Див. віртуалізацію. - Останній слайд показує стан. Додатковий слайд після дописів показує «Loading…», поки сторінка в дорозі, і помилку з Retry, коли вона не завантажилася, тож глядач ніколи не гортає в порожнечу. Це ще один випадок у itemBuilder, який рендерить усе, що стоїть за індексом.
- Завантаження наперед, від зміни слайда.
afterChangeпросить наступну сторінку, щойно глядач опиняється за три дописи до кінця. Сторінка, що не завантажилася, чекає на Retry, тож гортання туди й назад не повторює запит, що падає. Цей колбек описано разом з іншими подіями для React, Vue та Angular. - Ключі йдуть за дописами.
keyExtractorповертає id кожного допису, тож слайд зберігає свій елемент, коли позаду нього зʼявляється нова сторінка, а не перебудовується за індексом. Це пропс у React, Vue та Angular однаково. - Зображення вантажаться раніше за свій слайд. Слайд нижче ще не змонтовано, бо змонтовано лише видимий діапазон, як пояснює віртуалізація. Тож зображення кожної нової сторінки запитуються щойно вона надходить і беруться з кешу браузера, коли їхній слайд монтується.
- Клавіші й колесо вимкнено навмисно.
enableNavKeysслухає все вікно, аenableWheelперехоплює прокручування сторінки, поки вказівник над стрічкою. Обидва пасують стрічці на весь екран і заважають сторінці, у яку стрічку вбудовано, як тут, тож вони вимкнені, а дві кнопки натомість викликаютьprev()іnext()з Reel API. Свайп працює в будь-якому разі. - Ніщо не переживає стрічку. Кожен запит має
AbortController, який скасовується, коли стрічка демонтується, тож пізня відповідь ніколи не пише в стрічку, якої вже немає.
Наступні кроки
- Від сітки до плеєра - відкрийте повноекранний плеєр із сітки мініатюр і поверніться туди, де зупинилися
- Посібник з фреймворку - кожен пропс Reel і патерн, на яких стоїть цей рецептПосібник з фреймворку - кожен пропс Reel і патерн, на яких стоїть цей рецептПосібник з фреймворку - кожен пропс Reel і патерн, на яких стоїть цей рецепт