Backbonejs何时初始化集合

时间:2011-12-26 21:34:28

标签: javascript ruby-on-rails backbone.js url-routing

我正在使用rails 3.1 mongodb和backbonejs构建小型单页应用程序。

我有两个资源可以通过json api获得。我在骨干中创建了两个模型和集合,看起来像这样

https://gist.github.com/1522131

我也有两个独立的路由器

项目路由器 - https://gist.github.com/1522134 注意路由器 - https://gist.github.com/1522137

我使用github的backbonejs-rails gem生成它们,所以内部的代码只是模板。我在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()方法这个变量是空的。另外我应该可以从网址中重现笔记视图

/ 1 / notes / 5

project_id = 1 note_id = 5

什么是backbonejs解决此类问题的最佳做法?

1 个答案:

答案 0 :(得分:2)

为什么不在请求时懒惰加载笔记?这是一个例子:

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对象。我还在Note模型和Notes集合中添加了“state”属性。

你可能想要在某个地方(可能在你的路线内)初始化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;
  }
});

我没有对此进行过测试,因此可能存在一些错误,但我希望您明白这一点。