Подтвердить что ты не робот

Backbone.js: просмотр вложений через шаблоны

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

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

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

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

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

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

4b9b3361

Ответ 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(); 

Ответ 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>

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

то в вашем методе рендеринга просто отрисуйте отдельные элементы и добавьте их в элемент 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. Здесь я застреваю прямо сейчас:)