0

我的问题是围绕使用 Backbone 子查看渲染视图的最佳方式。

虽然有很多关于这个主题的博客,但我还没有找到任何可以应用于这个用例的实用想法。

背景故事

在页面加载时,主干获取并呈现远程模型和远程页面模板。

页面模板由 3 个字段集组成,每个字段集包含大量只读数据和图像,并带有一个 [edit] 按钮。

+-----------------------+ +-----------------------+
| ID: ViewA             | | ID: ViewB             |
|                       | |                       |
|                       | |                       |
|                  EDIT | |                  EDIT |
+-----------------------+ +-----------------------+
+-----------------------+
| ID: ViewC             |
|                       |
|                       |
|                  EDIT |
+-----------------------+

当用户单击 [edit] 时,我希望创建一个子视图,获取部分(下划线模板),将现有模型应用于它,最后,它替换字段集的 innerHTML。

这将使字段集中以前只读的内容可由用户编辑和保存。一旦被用户保存(或取消),它应该推回服务器,并重新呈现只读视图。

为了论证起见,假设模板托管在 /templates/edit/<fieldsetid>.html

这是现有的代码:

模型和集合

// Model
window.Page = Backbone.Model.extend();

// Collection
window.PageCollection = Backbone.Collection.extend({
    model: Page, 
    url: '/page/view.json'
});

风景

window.PageView = Backbone.View.extend({

    initialize:function () {
        this.model.bind("reset", this.render, this);
    },

    events:{
        'click fieldset a[role=edit-fieldset]' : 'edit'
    },

    edit: function(e){
        e.preventDefault();
        // @TODO Do some subview awesomeness here?
    },

    render:function (eventName) {
        _.each(this.model.models, function (data) {
            $(this.el).append(this.template({data: data.attributes}));
        }, this);
        return this;
    }

});

路由器

var AppRouter = Backbone.Router.extend({
    routes:{
        "page/view":"pageView"
    },
    pageView:function (action) {
        this.page = new PageCollection();
        this.pageView = new PageView({model:this.page});
        this.page.fetch();
        $('#content').html(this.pageView.render().el);
    }
});

模板加载器

// Borrowed from:
// http://coenraets.org/blog/2012/01/backbone-js-lessons-learned-and-improved-sample-app/
// Should probably move to RequireJS and AMDs

utils.loadTemplate(['PageView'], function() {
    var app = new AppRouter();
    Backbone.history.start();
});  

那么考虑到这一点,你的想法是什么?我在正确的轨道上吗?我应该看看另一种模式吗?

提前致谢。

4

1 回答 1

0

我通常处理这些情况的方式如下(使用上面现有的'loadTemplate'、Page 和 PageCollection 架构):

// Model
window.Page = Backbone.Model.extend();

// Collection
window.PageCollection = Backbone.Collection.extend({
    model: Page, 
    url: '/page/view.json'
});

window.PageView = Backbone.View.extend({

    template: templates.pageViewTemplate,

    render: function() {
        var html = this.map(function(model) {
            // Important! We don't need to store a reference to the FieldSetViews.
            // Simply render them and by passing in the model, we can update the view
            // as needed when the model changes.
            // 
            // This is also good to reduce the potential for memory-leaks.
            return new FieldSetView({
                model: model
            }).render();
        });

        // Do one DOM update.
        this.$el.html(html);

        return this.$el;
    }
});

window.FieldSetView = Backbone.View.extend({

    events: {
        "click .edit": "_onEdit"
    },

    template: templates.fieldSetTemplate,

    render: function() {
        // Replace the top-level div created by backbone with that of your 
        // template (i.e fieldset). This gets around having to use 
        // the tagName property which should really be in your template.
        this.setElement(this.template.render(this.model.toJSON()));

        return this.$el;
    },

    _onEdit: function(e) {
        // Handle edit mode here by passing the model to another view
        // or by enhancing this view to handle both edit and view states.
    }

});
于 2013-04-07T18:02:22.030 回答