javascript Backbone.js:通过模板嵌套视图

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7113049/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 22:59:48  来源:igfitidea点击:

Backbone.js: nesting views through templating

javascriptjquerybackbone.jstemplating

提问by user802232

Is it technically possible to nest views, using templating, something like that:

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

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

I can put all the stuff in the render method as well, but templating gives much more room for flexibility and layout.

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

I tried the aforementioned variant, but all I get as a result on the screen is [HTMLDivElement].

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

If I try to extract just the HTML out ouf it, using jQuery's HTML, I get it rendered, but it turns out that the DOM nodes that get printed out are different from the ones that the views hold a reference to, because no interaction whatsoever with those DOM nodes is possible using the view instance. For instance if within the view I say $(this.el).hide(), nothing will happen.

如果我尝试使用 jQuery 的 HTML 仅提取出它的 HTML,我会得到它的呈现,但结果是打印出来的 DOM 节点与视图持有引用的节点不同,因为没有任何交互使用视图实例可以使用这些 DOM 节点。例如,如果在我说的视图中$(this.el).hide(),什么都不会发生。

What is the proper way, if any?

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

回答by Skylar Anderson

I typically render the parent view first. I then use the this.$('selector')method to find a child element that I can use as the el of the child view.

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

Here is a full example:

这是一个完整的例子:

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

回答by Alessandro Giannone

The accepted answer has a major flaw, which is the fact that the ChildView is going to be re-initialised everytime it's rendered. This means you will lose state and potentially have to re-initialised complicated views on each render.

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

I wrote a blog about this here: http://codehustler.org/blog/rendering-nested-views-backbone-js/

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

To summarise though, I would suggest using something like this:

总而言之,我建议使用这样的东西:

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

You do not need to extend the Backbone view if you don't want to, the renderNested method could be put anywhere you like.

如果你不想,你不需要扩展 Backbone 视图,renderNested 方法可以放在你喜欢的任何地方。

With the code above, you can now initialise the ChildView in the initialisation method and then simply render it when render() is called.

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

回答by Brave Dave

Check out the Backbone.Subviewsmixin. It is a minimalist mixin built for managing nested views and does not re-initialize the child views every time the parent is rendered.

查看Backbone.Subviews混合。它是为管理嵌套视图而构建的极简主义 mixin,并且不会在每次呈现父视图时重新初始化子视图。

回答by Bryce Fischer

I don't know about within a template itself, but I've done it with tables and lists before. In the outer template, just have the stub:

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

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

and for the individual items: <%= field1 %>

对于单个项目:<%= field1 %>

then in your render method, just render the individual items and append them to the tbody element...

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

回答by Andrey Petrov

The decision to initialize a new object every time you render seems to me very inefficient. Particularly this:

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

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

Ideally the Rendering of the parent should be something like

理想情况下,父级的渲染应该是这样的

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

And the children creation should happen only when initializing the parent:

并且仅在初始化父级时才应该创建子级:

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

the problem is that we do not have selector1 and selector2 before rendering the parent template. This is where I am stuck at right now :)

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