Backbonejs 何时初始化集合

发布于 2024-12-23 10:18:28 字数 999 浏览 0 评论 0原文

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

我有两个可通过 json api 使用的资源。我在主干中创建了两个模型和集合,如下所示

https://gist.github.com/1522131

我还有两个单独的路由器

项目路由器 - https://gist.github.com/1522134 笔记路由器 - https://gist.github.com/1522137

我用backbonejs-rails gem 生成了它们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/notes/5

project_id = 1 note_id=5

在backbonejs中解决此类问题的最佳实践是什么?

I'm building small one page application with rails 3.1 mongodb and backbonejs.

I have two resources available through json api. I created two models and collections in backbone which look like this

https://gist.github.com/1522131

also I have two seprate routers

projects router - https://gist.github.com/1522134
notes router - https://gist.github.com/1522137

I generated them with backbonejs-rails gem from github so code inside is just template. I initialize my basic router inside index.haml file

#projects

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

    new JsonApi.Routers.NotesRouter();

    Backbone.history.start();
  });

I don't want fetch notes when application is starting, because there is big chance that user will never look inside notes. So there isn't good reason to fetch it on start. Inside NotesRouter in all action I rely on @notes variable but without .fetch() method this variable is empty. Also I should can reproduce notes view from url like

/1/notes/5

project_id = 1
note_id = 5

What is best practices in backbonejs to solve this kind of problem ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我不吻晚风 2024-12-30 10:18:28

为什么不在需要时延迟加载笔记呢?下面是一个示例:

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;
  }
});

我还没有对此进行测试,因此可能存在一些错误,但我希望您能理解。

Why don't you lazy load the notes when it's requested? Here's an example:

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;
                }
            });
        }
    }
});

In this example, I'm defining a NoteCache object that manages the lazy loading. I also add a "state" property to the Note model and Notes collection.

You'll probably want to initialize NoteCache somewhere (probably inside your route) and whenever you want a note or notes, just do this:

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

Now inside your view, you'll want to listen for state changes in case the note/notes is not loaded yet:

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;
  }
});

I haven't tested this, so there may be some bugs, but I hope you get the idea.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文