Backbone.js: вложение представлений через шаблоны - PullRequest
18 голосов
/ 18 августа 2011

Технически возможно ли вложить представления с использованием шаблонов, что-то в этом роде:

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

Я также могу поместить все вещи в метод рендеринга, но шаблоны дают гораздо больше места для гибкости и макета.

Я пробовал вышеупомянутый вариант, но все, что я получаю в результате на экране, это [HTMLDivElement].

Если я попытаюсь извлечь из него только HTML-код, используя HTML-код jQuery, я получу его визуализацию, но оказывается, что распечатываемые DOM-узлы отличаются от тех, на которые ссылаются представления.к, потому что никакое взаимодействие с этими узлами DOM невозможно с использованием экземпляра представления.Например, если в представлении я говорю $(this.el).hide(), ничего не произойдет.

Каков правильный путь, если таковой имеется?

Ответы [ 5 ]

29 голосов
/ 23 августа 2011

Обычно я сначала отображаю родительский вид.Затем я использую метод 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(); 
14 голосов
/ 04 января 2013

Принятый ответ имеет большой недостаток, который заключается в том, что 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 ().

2 голосов
/ 01 февраля 2013

Проверьте Backbone.Subviews mixin.Это минималистичный миксин, созданный для управления вложенными представлениями, и он не выполняет повторную инициализацию дочерних представлений при каждом отображении родительского представления.

1 голос
/ 20 августа 2011

Я не знаю о самом шаблоне, но я делал это раньше с помощью таблиц и списков.Во внешнем шаблоне просто добавьте заглушку:

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

, а для отдельных элементов: <% = field1%>

, затем в вашем методе рендеринга просто визуализируйте отдельные элементы и добавьтеих к элементу tbody ...

0 голосов
/ 24 сентября 2012

Решение инициализировать новый объект каждый раз, когда вы визуализируете, кажется мне очень неэффективным.В частности это:

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 до рендеринга родительского шаблона.Вот где я застрял прямо сейчас:)

...