【问题标题】:Backbone.js: nesting views through templatingBackbone.js:通过模板嵌套视图
【发布时间】:2011-10-30 02:15:58
【问题描述】:

在技术上是否可以使用模板嵌套视图,例如:

<%= new PhotoCollectionView({model:new PhotoCollection(model.similarPhotos)}).render().el) %>

我也可以将所有东西都放在渲染方法中,但是模板为灵活性和布局提供了更多空间。

我尝试了上述变体,但我在屏幕上得到的结果是[HTMLDivElement]

如果我尝试仅从其中提取 HTML,使用 jQuery 的 HTML,我会对其进行渲染,但事实证明,打印出来的 DOM 节点与视图所引用的节点不同,因为使用视图实例无法与这些 DOM 节点进行任何交互。例如,如果在视图中我说$(this.el).hide(),则不会发生任何事情。

如果有的话,正确的方法是什么?

【问题讨论】:

  • 我不确定这种技术在技术上是否可行,但我建议不要这样做,因为模板应该只包含简单的条件语句而不是任何应用程序逻辑。应用程序逻辑应保留在您的视图中。这样一来,关注点就可以明确分离,并且您的应用程序将更易于维护。
  • 你可以使用 React.js 嵌套视图

标签: javascript jquery backbone.js templating


【解决方案1】:

我通常先渲染父视图。然后我使用this.$('selector') 方法找到一个可以用作子视图的el 的子元素。

这是一个完整的例子:

var ChildView = Backbone.View.extend({
  //..
})

var ParentView = Backbone.View.extend({
  template: _.template($('#parent-template').html()),
  initialize: function() {
    _.bindAll(this, 'render');
  }
  render: function() {
    var child_view = new ChildView({ el: this.$('#child-el') }); //This refers to ParentView. 
    return this;
  }
});

var v = new ParentView();
v.render(); 

【讨论】:

  • 嗯,是的......我最终做了同样的事情
  • 这似乎有点低效。每次渲染父视图时,您都在重新初始化子视图。
  • 同意亚历山德罗。除了效率低下之外,每次渲染父视图时,您还会在子视图中失去动态状态。查看Backbone.Subviews 了解即用型简约解决方案
  • 您应该在initialize中创建子视图,并将其存储为父视图的属性。然后在父渲染函数内的子视图上调用渲染。
【解决方案2】:

接受的答案有一个重大缺陷,即 ChildView 每次渲染时都会重新初始化。这意味着您将失去状态,并且可能必须在每次渲染时重新初始化复杂的视图。

我在这里写了一篇关于这个的博客:http://codehustler.org/blog/rendering-nested-views-backbone-js/

总而言之,我建议使用如下内容:

var BaseView = Backbone.View.extend({

    // Other code here...

    renderNested: function( view, selector ) {
        var $element = ( selector instanceof $ ) ? selector : this.$el.find( selector );
        view.setElement( $element ).render();
    }
});

var CustomView = BaseView.extend({

    // Other code here...

    render: function() {
        this.$el.html( this.template() );
        this.renderNested( this.nestedView, ".selector" );
        return this;
    }
});

如果您不想扩展 Backbone 视图,则无需扩展,renderNested 方法可以放在您喜欢的任何位置。

使用上面的代码,您现在可以在初始化方法中初始化 ChildView,然后在调用 render() 时简单地渲染它。

【讨论】:

    【解决方案3】:

    查看Backbone.Subviews mixin。它是一个极简的 mixin,用于管理嵌套视图,并且不会在每次渲染父视图时重新初始化子视图。

    【讨论】:

      【解决方案4】:

      我不知道模板本身,但我以前用表格和列表做过。在外部模板中,只有存根:

      <script type="text/template" id="table-template">
          <table>
              <thead>
                  <th>Column 1</th>
              </thead>
              <tbody>
              </tbody>
          </table>
      </script>
      

      对于单个项目:

      然后在您的渲染方法中,只需渲染各个项目并将它们附加到 tbody 元素...

      【讨论】:

        【解决方案5】:

        在我看来,每次渲染时都初始化一个新对象的决定效率很低。 特别是这个:

        render: function() {
            var child_view = new ChildView({ el: this.$('#child-el') }); //This refers to ParentView. 
            return this;
          }
        

        理想情况下,父级的渲染应该类似于

        render: function() {
           this.$el.html(this.template());
           this.childView1.render();
           this.childView2.render();
        }
        

        只有在初始化父级时才应该创建子级:

        initialize: function() {
               this.childView1 = new ChildView1(selector1);
               this.childView2 = new ChildView2(selector2);
        } 
        

        问题是我们在渲染父模板之前没有selector1和selector2。这就是我现在所困的地方:)

        【讨论】:

        • 这似乎并没有真正回答这个问题,尽管这个建议似乎是合理的。一定要真正回答问题
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-03-21
        • 2011-12-15
        • 2012-12-16
        • 1970-01-01
        • 2013-05-06
        • 2015-10-13
        • 1970-01-01
        相关资源
        最近更新 更多