Backbonejs, когда инициализировать коллекции - PullRequest
1 голос
/ 27 декабря 2011

Я создаю небольшое одностраничное приложение с рельсами 3.1 mongodb и backbonejs.

У меня есть два ресурса, доступных через json api. Я создал две модели и коллекции в позвоночнике, которые выглядят так:

https://gist.github.com/1522131

также у меня есть два отдельных роутера

проекты маршрутизатора - https://gist.github.com/1522134 маршрутизатор заметок - https://gist.github.com/1522137

Я сгенерировал их с помощью гема backbonejs-rails из github, поэтому код внутри - это просто шаблон. Я инициализирую свой основной маршрутизатор в файле index.haml

#projects

:javascript
  $(function() {
    window.router = new JsonApi.Routers.ProjectsRouter({projects: #{@projects.to_json.html_safe}});

    new JsonApi.Routers.NotesRouter();

    Backbone.history.start();
  });

Я не хочу получать заметки при запуске приложения, потому что есть большая вероятность, что пользователь никогда не заглянет внутрь заметок. Так что нет веских причин, чтобы получить его на старте. Внутри NotesRouter во всех действиях я использую переменную @notes, но без метода .fetch () эта переменная пуста. Также я должен воспроизвести вид заметки с URL-адреса, как

/ 1 / заметки / 5

project_id = 1 note_id = 5

Каковы лучшие методы в backbonejs для решения такого рода проблем?

1 Ответ

2 голосов
/ 06 января 2012

Почему бы вам не лениво загружать заметки, когда они запрашиваются? Вот пример:

var State = Backbone.Model.extend({
    defaults: {
        ready: false,
        error: null
    }
});

var Note = Backbone.Model.extend({
    initialize: function () {
        this.state = new State();
    }
});

var Notes = Backbone.Collection.extend({
    model: Note,

    initialize: function () {
        this.state = new State();
    }
});

var NoteCache = Backbone.Model.extend({

    initialize: function () {
        this._loading = false;
        this._loaded = false;
        this._list = new Notes();
    },

    _createDeferred: function (id) {
        var note = new Note({ id: id });
        this._list.add(note);
        this._load();
        return note;
    },

    getNote: function (id) {
        return this._list.get(id) || this._createDeferred(id);
    },

    getNotes: function () {
        if (!this._loaded)
            this._load();

        return this._list;
    },

    _load: function () {

        var that = this;

        if (!this._loading) {

            this._list.state.set({ ready: false, error: null });

            this._loading = true;

            $.ajax({
                url: '/api/notes',
                dataType: 'json',
                cache: false,
                type: 'GET',
                success: function (response, textStatus, jqXHR) {

                    _.each(response.notes, function (note) {

                        var n = that._list.get(note.id);
                        if (n) {
                            n.set(note);
                        } else {
                            that._list.add(note, { silent: true });
                            n = that._list.get(note.id);
                        }
                        n.state.set({ ready: true, error: null });
                    });

                    that._list.state.set({ ready: true, error: null });
                    that._list.trigger('reset', that._list);
                    that._loaded = true;
                },
                error: function (jqXHR, textStatus, errorThrown) {
                    that._list.state.set({ error: 'Error retrieving notes.' });
                    that._list.each(function (note) {
                        note.state.set({ error: 'Error retrieving note.' });
                    });
                },
                complete: function (jqXHR, textStatus) {
                    that._loading = false;
                }
            });
        }
    }
});

В этом примере я определяю объект NoteCache, который управляет отложенной загрузкой. Я также добавляю свойство «state» в модель Note и коллекцию Notes.

Вы, вероятно, захотите инициализировать NoteCache где-нибудь (возможно, внутри вашего маршрута), и всякий раз, когда вам нужна заметка или заметки, просто сделайте это:

var note = noteCache.getNote(5);
var notes = noteCache.getNotes();

Теперь внутри вашего представления вы захотите прослушать изменения состояния, если заметка / заметки еще не загружены:

var NoteView = Backbone.View.extend({
  initialize: function(){
    this.note.state.bind('change', this.render, this);
  },
  render: function(){
     if (this.note.state.get('error') {
       // todo: show error message
       return this;
     }

     if (!this.note.state.get('ready') {
       // todo: show loader animation
       return this;
     }

     // todo: render view
     return this;
  }
});

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

...