Backbone.js: выборка моделей и их рендеринг

Я изучаю разработку JavaScript MVC-приложений с использованием Backbone.js и проблемы с отображением коллекции моделей в представлении. Вот что я хочу сделать:

  • После завершения загрузки страницы извлекает данные с сервера в виде коллекции моделей

  • Отобразить их в представлении

Это все, что я хочу сделать, и вот что я до сих пор:

$(function(){

    "use strict";

    var PostModel = Backbone.Model.extend({});

    var PostCollection = Backbone.Collection.extend({
        model: PostModel,
        url: 'post_action.php'
    });

    var PostView = Backbone.View.extend({
        el: "#posts-editor",        

        initialize: function(){
            this.template = _.template($("#ptpl").html());
            this.collection.fetch({data:{fetch:true, type:"post", page:1}});
            this.collection.bind('reset', this.render, this);
        },

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

    var postList = new PostCollection();
    postList.reset();
    var postView = new PostView({
        collection: postList
    });

});

Проблема

Насколько я знаю, Chrome регистрирует ответ с сервера, и он в формате JSON, как я хочу. Но на мой взгляд это не делает. В консоли нет видимых ошибок.

На сервере есть обработчик, который принимает параметры GET и эхо некоторых JSON: http://localhost/blog/post_action.php?fetch=true&type=post&page=1

[
   {
      "username":"admin",
      "id":"2",
      "title":"Second",
      "commentable":"0",
      "body":"This is the second post."
   },
   {
      "username":"admin",
      "id":"1",
      "title":"Welcome!",
      "commentable":"1",
      "body":"Hello there! welcome to my blog."
   }
]

Ответы

Ответ 1

В вашем коде есть 2 потенциальных проблемы.

  • Обратный вызов прослушивателя событий должен быть зарегистрирован перед вызовом collection.fetch(). В противном случае вы можете пропустить первое событие reset, поскольку оно может быть запущено до регистрации слушателя.

  • Событие reset недостаточно для обеспечения повторного отображения представления при каждом обновлении коллекции.

Кроме того, обратите внимание, что использовать форму object.listenTo() для привязки событий является хорошей практикой, так как она обеспечит правильную регистрацию при закрытии представления. В противном случае вы можете получить так называемое Backbone zombies. Вот решение.

this.listenTo( this.collection, 'reset add change remove', this.render, this );
this.collection.fetch({ data: { fetch:true, type:"post", page:1 } });

Обратите внимание, как вы можете зарегистрировать несколько событий из одного и того же объекта, разделив их пробелом.

Ответ 2

изменить

this.collection.bind('reset', this.render, this);

к

this.collection.bind('sync', this.render, this);

Проблема заключается в том, что вы выполняете reset только один раз, в начале. И в то время вам нечего делать. В следующий раз, когда вы получите свою коллекцию, событие reset не срабатывает, потому что вы выбираете коллекцию без опции {reset: true}.

Ответ 3

Измените эту строку

this.collection.bind('reset', this.render, this);

to

this.listenTo(this.collection, 'reset', this.render);

Ответ 4

При извлечении вашей коллекции событие reset больше не запускается по умолчанию. (Я считаю, начиная с версии 1.0) Чтобы иметь Backbone fire событие reset, когда коллекция была выбрана, теперь вы должны вызвать метод выборки следующим образом:

this.collection.fetch({reset: true});