Рендеринг коллекции Backbone.js

Я - Backbone.js n00b и пытаюсь обнять его. Я знаю, как визуализировать модель с использованием представления и встроенного шаблона templates для underscore.js. Теперь я пытаюсь сделать коллекцию и то, где я застрял. Здесь нет сервера, поэтому я ничего не делаю удаленно, просто простая HTML-страница с некоторым JavaScript.

ContinentModel = Backbone.Model.extend({});

ContinentsCollection = Backbone.Collection.extend({
  model: ContinentModel,

  initialize: function () {
    this.continentsView = new ContinentsView;
    this.bind("reset", this.continentsView.render);
  }
});

ContinentsView = Backbone.View.extend({
  el: '#continents',
  template: _.template($('#continents-template').html()),

  render: function() {
    var renderedContent = this.template(this.collection.toJSON());
    $(this.el).html(renderedContent);
    return this;
  }
});

$(function() {
  var continentsCollection = new ContinentsCollection();
  continentsCollection.reset([{name: "Asia"}, {name: "Africa"}]);
});

Он разбивается на строку атрибута шаблона в представлении, но я не уверен, что там, где мне нужно посмотреть. Могу ли я представить коллекцию или я полностью упустил точку здесь (возможно, коллекции просто группируют объекты, и я не должен рассматривать ее как список, который я могу отобразить)?

Спасибо за помощь...

Ответы

Ответ 1

Проблема заключается в том, что при определении ContinentsView шаблон оценивается и использует $('#continents-template') - но DOM еще не готов, поэтому он не находит шаблон.

Чтобы решить эту проблему, просто переместите назначение шаблона в функцию инициализации:

ContinentsView = Backbone.View.extend({
  el: '#continents',
  initialize: function() {
     this.template = _.template($('#continents-template').html());
  }
  ...

Что касается коллекций, да, они группируют объекты, в частности, наборы моделей.

Вы должны сделать код, чтобы модели (и коллекции) НЕ знали о представлениях, но только представления о моделях.

ContinentModel = Backbone.Model.extend({});

ContinentsCollection = Backbone.Collection.extend({
  model: ContinentModel,
  // no reference to any view here    
});

ContinentsView = Backbone.View.extend({
  el: '#continents',

  initialize: function() {
    this.template = _.template($('#continents-template').html());
    // in the view, listen for events on the model / collection
    this.collection.bind("reset", this.render, this);
  },

  render: function() {
    var renderedContent = this.template(this.collection.toJSON());
    $(this.el).html(renderedContent);
    return this;
  }
});

$(function() {
  var continentsCollection = new ContinentsCollection();
  continentsCollection.reset([{name: "Asia"}, {name: "Africa"}]);
  // initialize the view and pass the collection
  var continentsView = new ContinentsView({collection: continentsCollection});
});

Ответ 2

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

Backbone.CollectionView - это класс надежного класса коллекций, который обрабатывает выбор моделей в ответ на щелчки мыши, переупорядочивая коллекцию на основе перетаскивания, фильтрация видимых моделей и т.д.

Несколько популярных фреймворков, построенных поверх базовой линии, также предоставляют простые классы просмотра коллекции, такие как Backbone.Marionette, Chaplin и Менеджер макетов.

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