Backbone.js:应该.render()和.remove()能够互相反转吗?

时间:2012-04-18 19:05:58

标签: javascript model-view-controller architecture backbone.js

因为Backbone.js非常灵活,我想知道某些事情的最佳方法。在这里,我想知道我是否应该构建我的应用程序的视图,以便'.render()'和'.remove()'正确地相互反转。

首先,看起来最干净的方法是将视图传递给要附加的ID或jQuery元素。如果事情以这种方式完成,调用'.render()'将无法正确替换DOM中的视图,因为主元素永远不会放回DOM中:

App.ChromeView = Backbone.View.extend({
  render: function() {
    // Instantiate some "sub" views to handle the responsibilities of
    // their respective elements.
    this.sidebar = new App.SidebarView({ el: this.$(".sidebar") });
    this.menu = new App.NavigationView({ el: this.$("nav") });
  }
});

$(function() {
  App.chrome = new App.ChromeView({ el: $("#chrome") });
});

我似乎更喜欢将它设置为.remove()和.render()完全相反:

App.ChromeView = Backbone.View.extend({
  render: function() {
    this.$el.appendTo('body');
    this.sidebar = new App.SidebarView({ el: this.$(".sidebar") });
    this.menu = new App.NavigationView({ el: this.$("nav") });
  }
});

$(function() {
  App.chrome = new App.ChromeView();
});

Backbone.js社区说了什么?应该.remove()和.render()是同一枚硬币的两面吗?

3 个答案:

答案 0 :(得分:2)

我更喜欢render不会将视图的元素附加到dom。我认为这促进了松散耦合,高内聚,视图重用以及便于单元测试。我将渲染的元素附加到容器,直到路由器或主“布局”类型的容器视图。

关于remove的好处是它在没有知道父元素的视图的情况下工作,因此仍然是松散耦合和可重用的。我绝对不喜欢将布局HTML(#main或其他)中的随机DOM选择器放入我的视图中。那里的联系绝对不好。

我会注意到在某些恼人的情况下,像chosen jQuery plugin之类的东西需要在元素附加到DOM之后运行一些代码。对于这些情况,我通常在视图中实现postAttach()回调,并尝试尽可能减少代码量。

答案 1 :(得分:2)

是的,内部View.remove()非常激进

建议使用外部el再次重新创建View我习惯用这样重写:

remove: function(){
  this.$el.empty();
  return this;
}

但我认为框架不应该实现 magic 行为以避免此外部DOM元素删除

这种框架行为是积极的,没问题,但如上所述,在需要时自定义它是非常便宜的。

答案 2 :(得分:0)

这个怎么样?如果我们只有.initialize和.render获取parentSelector属性,我们可以这样做并最终使用以下用法:

  • 松散耦合
  • 可逆.remove()/。render()
  • 单一方法 实例化&渲染调用方法

例如:

// Bootstrap file
curl(['views/app']).then(
    function(App){
        app = new App('body');
    });



// view/app.js
   define([
        'text!views/app.tmpl.html'
    ,   'link!views/app.css'
    ]
,   function (template) {

    var App

    // Set up the Application View
    App = Backbone.View.extend({
        // Standard Backbone Methods
        initialize: function (parentSel) {
            console.log('App view initialized')
            if (parentSel) { this.render(parentSel) }
        }
    ,   render: function (parentSel) {
            if (parentSel) { this._sel = parentSel } // change the selector if render is called with one
            if (!this._sel) { return this } // exit if no selector is set

            this.$el.appendTo(this._sel)

            this.$el.html(
                this.compiledTemplate({ 'content':'test content' })
            );
            return this
        }
        // Custom Properties
    ,   compiledTemplate: _.template(template)
    })

    return App
});


// External usage
// I can call .remove and .render all day long now:
app.remove()
app.render()
app.remove()