Infinite scrolling — это техника подгрузки данных по мере прокрутки страницы, что позволяет отображать большое количество элементов без необходимости загружать их все сразу. В Backbone.js реализация такой функциональности строится на сочетании моделей, коллекций и представлений, а также грамотного управления событиями.
В Backbone.js коллекции (Backbone.Collection) служат
основой для работы с наборами данных. Для реализации infinite scrolling
коллекция должна поддерживать постраничное получение
данных с сервера. Стандартный подход — расширить коллекцию и
добавить методы управления страницами:
var PaginatedCollection = Backbone.Collection.extend({
url: '/api/items',
page: 1,
perPage: 20,
fetching: false,
fetchNextPage: function() {
if (this.fetching) return;
this.fetching = true;
this.fetch({
remove: false,
data: { page: this.page, per_page: this.perPage },
success: () => {
this.page += 1;
this.fetching = false;
},
error: () => {
this.fetching = false;
}
});
}
});
Ключевые моменты:
remove: false предотвращает очистку текущих моделей при
добавлении новых.fetching блокирует параллельные запросы.page после успешного запроса гарантирует
корректную постраничную загрузку.Для управления infinite scrolling создаётся представление, которое отслеживает прокрутку страницы или контейнера. При достижении определённого порога вызывается метод загрузки следующей страницы коллекции.
var InfiniteView = Backbone.View.extend({
el: '#items-container',
initialize: function() {
this.listenTo(this.collection, 'add', this.renderItem);
$(window).on('scroll', this.checkScroll.bind(this));
},
renderItem: function(model) {
var itemHtml = `<div class="item">${model.get('name')}</div>`;
this.$el.append(itemHtml);
},
checkScroll: function() {
var scrollPosition = $(window).scrollTop() + $(window).height();
var threshold = $(document).height() - 100;
if (scrollPosition >= threshold) {
this.collection.fetchNextPage();
}
}
});
Особенности:
listenTo позволяет автоматически
реагировать на добавление новых моделей в коллекцию.checkScroll вычисляет текущую позицию прокрутки
относительно нижнего края документа.100px перед концом документа уменьшает задержку
при подгрузке данных.При больших объёмах данных важно избежать замедления браузера и перегрузки DOM:
Фрагменты DOM (DocumentFragment) Добавление нескольких элементов сразу через фрагмент ускоряет рендеринг:
renderItemsBatch: function(models) {
var fragment = document.createDocumentFragment();
models.forEach(model => {
var div = document.createElement('div');
div.className = 'item';
div.textContent = model.get('name');
fragment.appendChild(div);
});
this.el.appendChild(fragment);
}Дебаунс событий прокрутки Частые срабатывания
события scroll нагружают браузер. Использование дебаунса
снижает нагрузку:
checkScroll: _.debounce(function() {
var scrollPosition = $(window).scrollTop() + $(window).height();
if (scrollPosition >= $(document).height() - 100) {
this.collection.fetchNextPage();
}
}, 200);Удаление неактивных элементов Для длинных списков полезно удалять элементы, вышедшие за пределы видимой области (виртуализация).
Для устойчивости приложения важно информировать пользователя и корректно обрабатывать сбои сети:
var LoaderView = Backbone.View.extend({
el: '#loader',
initialize: function() {
this.listenTo(this.collection, 'request', this.show);
this.listenTo(this.collection, 'sync error', this.hide);
},
show: function() {
this.$el.show();
},
hide: function() {
this.$el.hide();
}
});
request срабатывает при начале запроса
коллекции.sync и error — при завершении или
неудаче.Infinite scrolling требует согласованного API на сервере:
page и per_page.Пример ответа API:
{
"items": [
{"id": 1, "name": "Item 1"},
{"id": 2, "name": "Item 2"}
],
"page": 1,
"per_page": 20,
"total_pages": 5
}
Коллекция Backbone может использовать эту информацию для контроля загрузки:
if (response.page >= response.total_pages) {
this.hasMore = false;
}
window
можно использовать отдельный блок с внутренней прокруткой.Infinite scrolling в Backbone.js строится на принципах модульности: коллекция управляет данными, представление — отображением, а события Backbone обеспечивают синхронизацию и реактивность. Такой подход позволяет создавать масштабируемые интерфейсы с динамической подгрузкой данных.