3

因为 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() 应该是同一枚硬币的两面吗?

4

3 回答 3

2

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

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

我会注意到,在某些烦人的情况下,某些东西,比如选择的 jQuery 插件,需要在元素附加到 DOM 之后运行一些代码。对于这些情况,我通常会在视图中实现postAttach()回调,并尽量保持那里的代码量尽可能少。

于 2012-04-18T19:15:36.040 回答
2

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

对于使用外部重新创建视图的建议,el我习惯于像这样重写它:

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

但我不认为框架应该实现魔术行为来避免这种外部 DOM 元素删除

这个框架的行为是激进的,好的,但是正如我们上面看到的,在需要的时候定制它是非常便宜的。

于 2012-04-18T20:21:46.773 回答
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()
于 2012-04-18T20:52:43.640 回答