бесконечная прокрутка с ember.js (ленивая загрузка)

У меня есть представление, в котором пользователь может прокручивать большое количество элементов, и я хотел бы реализовать бесконечную прокрутку, чтобы обеспечить постепенную загрузку контента.

Похоже, что некоторые люди выполнили разбиение на страницы но Google не призывает никого обсуждать, как они создавали бесконечные списки с Ember / Ember Data. Кто-нибудь уже работал с этим и есть сообщение в блоге / пример кода, которым можно поделиться?


person outside2344    schedule 10.08.2012    source источник
comment
Очень хороший вопрос, надеюсь, у вас будут ответы, так как здесь я совершенно не знаю, как это сделать, и я почти уверен, что мне это понадобится.   -  person sly7_7    schedule 10.08.2012
comment
Концепция бесконечной прокрутки кажется довольно простой, вы просто листаете свои данные, и вместо того, чтобы отбрасывать существующий контент из пользовательского интерфейса и заменять его тем, что вы принесли из магазина (обычно представления табличных данных), вы добавите его в контейнер (скажем, и ul с добавленными к нему несколькими li элементами), но может быть задействовано что-то еще (например, кеширование и тому подобное). Я хотел бы увидеть пример этого, так как у меня сейчас нет времени, чтобы попробовать его кодировать.   -  person MilkyWayJoe    schedule 10.08.2012
comment
Интересует и этот вопрос - особенно в отношении того, сколько данных должно быть в магазине и еще не отображаться (кеширование, на которое ссылается @MilkyWayJoe). В связи с этим, если основные результаты изменились (например, были опубликованы твиты), как лучше всего справиться с изменением разбивки на страницы?   -  person dechov    schedule 11.08.2012
comment
если событие, касающееся бесконечной прокрутки, происходит на стороне сервера - как вы упомянули, был добавлен новый твит - приложение должно использовать одну из этих постоянно подключенных фреймворков (например, node.js, signalr.js), чтобы запустить что-то на клиенте для загрузить больше результатов. Кроме того, у клиента должно быть что-то, наблюдающее за прокруткой страницы - очевидно, - чтобы запустить функцию, которая потребляет данные с сервера.   -  person MilkyWayJoe    schedule 11.08.2012


Ответы (4)


Вы знали о недавно выпущенном компоненте Ember.ListView?

https://github.com/emberjs/list-view

Об этом было объявлено на февральской встрече Ember в Сан-Франциско. Вот слайд-шоу от Эрика Брина, одного из разработчиков Ember Core, о его использовании:

http://talks.erikbryn.com/ember-list-view/

person commadelimited    schedule 13.03.2013
comment
можно ли это использовать с ember-data и последовательными запросами страниц? - person Christopher Manning; 18.03.2013
comment
По умолчанию может использоваться с Ember.Data. Я верю, что он выполняет разбиение на страницы за вас. Посмотрите вторую ссылку выше, так как в ней есть видео презентации, которую сделал Эрик Брин. - person commadelimited; 19.03.2013
comment
Элемент управления знает об обновлении своего базового содержимого, и если он изменится, список будет обновляться. Не похоже на бесконечную прокрутку. - person dmarr; 21.03.2013
comment
Насколько я понимаю, есть несколько проблем, которые необходимо решить с помощью этого элемента управления. Во-первых, это собственный фрейм с собственным скроллером - ни во что вроде бутстрапа не влезает. Во-вторых, ember-data не выдает изменяемые наборы данных, поэтому для подключения всего требуется немного больше. - person dineth; 22.03.2013

Я реализовал механизм бесконечной прокрутки в GitHub Dashboard проекте, который я сейчас разрабатываю. Эта функция добавлена ​​в коммит 68d1728.

Основная идея состоит в том, чтобы иметь LoadMoreView, который вызывает метод loadMore на контроллере каждый раз, когда представление отображается в текущем окне просмотра. Для этого я использую подключаемый модуль jQuery inview. Он позволяет вам зарегистрироваться для inview события, которое запускается, когда элемент указанного селектора отображается на экране и когда он исчезает.

Контроллер также имеет свойства, которые указывают, есть ли еще элементы для загрузки и есть ли в данный момент выбранные элементы. Эти свойства называются canLoadMore и isLoading.

LoadMoreView в основном выглядит так:

App.LoadMoreView = Ember.View.extend({
  templateName: 'loadMore',
  didInsertElement: function() {
    var view = this;
    this.$().bind('inview', function(event, isInView, visiblePartX, visiblePartY) {
      if (isInView) Ember.tryInvoke(view.get('controller'), 'loadMore');
    });
  }
});

где шаблон loadMore определяется следующим образом:

{{#if isLoading}}
    fetching some more stuff <img width="10" src="img/ajax-loader.gif" >
{{else}}
    {{#if canLoadMore}}
        <a {{action "loadMore" target="controller" }}>click to load more items</a>
    {{else}}
        <i>no more items</i>
    {{/if}}
{{/if}}

Контроллер, который обрабатывает выборку дополнительных элементов, реализуется следующим образом. Обратите внимание, что в методе loadMore выполняется запрос к хранилищу, который загружает определенную страницу записей для модели.

App.EventsController = Ember.ArrayController.extend({
  currentPage: 1,

  canLoadMore: function() {
    // can we load more entries? In this example only 10 pages are possible to fetch ...
    return this.get('currentPage') < 10;
  }.property('currentPage'),

  loadMore: function() {
    if (this.get('canLoadMore')) {
      this.set('isLoading', true);
      var page = this.incrementProperty('currentPage');

      // findQuery triggers somehing like /events?page=6 and this
      // will load more models of type App.Event into the store
      this.get('store').findQuery(App.Event, { page: page });
    } else {
      this.set('isLoading', false);
    }
  }
});

Осталось только изначально установить content контроллера на результат функции filter, поэтому content обновляется, когда новые модели загружаются в хранилище (что происходит из-за метода findQuery в loadMore контроллера). Кроме того, хэш query добавляется при вызове filter. Это гарантирует выполнение первоначального запроса к серверу.

App.eventsController = App.EventsController.create({
    content: []
});

var events = App.store.filter(App.Event, { page: 1 }, function(data) {
    // show all events; return false if a specific model - for example a specific
    // type of event - shall not be included
    return true;
});
person pangratz    schedule 12.08.2012
comment
Очень полезно, но почему вы используете фильтр? На самом деле вы ничего не фильтруете (например, return true), поэтому есть ли другие преимущества использования фильтра? - person Alexander Wallace Matchneer; 24.09.2012
comment
Почему вы используете Ember.tryInvoke? - person Jakub Arnold; 19.02.2013
comment
@JakubArnold, чтобы убедиться, что вызов не вызывает ошибки в случае, когда controller не реализует loadMore ... - person pangratz; 20.02.2013
comment
Я действительно не дошел до последнего шага, var event = .... Почему это сохраняется в переменной? Где используется переменная и для чего нужен фильтр? - person polyclick; 20.02.2013
comment
Я заметил, что первый вызов службы по-прежнему получает все элементы вместо содержимого первой страницы. Есть мысли по этому поводу? - person polyclick; 05.03.2013
comment
Замечательный ответ. Спасибо!! Я сделал версию, основанную на вашей работе, на случай, если она будет полезна другим. github.com/ducationHiD/Mobile_app/ - person iHiD; 01.04.2013

Я пишу плагин бесконечной разбивки на страницы для Ember на основе работы @pangratz.

Пожалуйста, сообщите о любых проблемах, если у вас есть вопросы или улучшения, которые вам нужны.

person iHiD    schedule 02.04.2013
comment
Я написал миксин с бесконечной прокруткой для ember js github. com / jeswinjose / Ember-Plugins / blob / master / - person jsHero; 25.03.2015

Я бы рекомендовал использовать надстройку Ember Infinity. Он поддерживает Ember с 1.10 по 2.0+. Его относительно легко настроить. Вам нужно только изменить свой маршрут и шаблон.

Маршрут (Product пример модели):

import InfinityRoute from 'ember-infinity/mixins/route';

export default Ember.Route.extend(InfinityRoute, {
  model() {
    /* Load pages of the Product Model, starting from page 1, in groups of 12. */
    return this.infinityModel('product', { perPage: 12, startingPage: 1 });
  }
});

Шаблон:

{{#each model as |product|}}
  ...
{{/each}}

{{infinity-loader infinityModel=model}}

Когда компонент {{infinity-loader}} становится видимым, он отправляет действие на ваш маршрут, поэтому он знает, что нужно обновить массив модели новыми (извлеченными) записями.

Первый запрос будет отправлен по адресу:

/products?per_page=12&page=1

Таким образом, вам также необходимо подготовить свой серверный API для обработки этих параметров запроса. Очевидно, что его можно настроить. Взгляните на раздел "Расширенное использование" в Readme.

Примечание.

Как использование ListView (ответ @ commadelimited), так и представления с ArrayController (ответ @ pangratz) устарели / удалены, поскольку Ember 2.0 является стабильной версией.

person Daniel Kmak    schedule 27.09.2015