Можно ли использовать представления/шаблоны Backbone больше как типичные шаблоны MVC на стороне сервера, а не пустые контейнеры и множество дополнений?

Один из разработчиков интерфейса задал мне этот вопрос, и я не был точно уверен, как сформулировать свою позицию, но он заставил меня задуматься:

Таким образом, соглашение в Backbone (или Backbone.Marionette) состоит в том, чтобы отображать представление, связанное с шаблоном, а затем выгружать или добавлять созданный/композитный HTML-код результирующего представления в существующий контейнер, как таковой:

this.$el.append(this.subview.render().$el);

Однако для этого, конечно же, требуется элемент DOM на странице, которая уже была визуализирована, чтобы выгрузить в нее это только что визуализированное представление. Это приводит к следующим явлениям:

<ul id="scheduler-loadroutegroups" class="full-height"></ul>

or

collectionView.$("#scheduler-loadroutegroups").append(itemView.el);

То есть пустые контейнеры, которые в конечном итоге ожидают содержимого.

Очевидно, что этот шаблон рендеринга и добавления является основной концепцией Backbone, и наличие контейнеров для размещения контента кажется абсолютно необходимым.

Вопрос моего коллеги заключался в том, можно ли использовать шаблон шаблона MVC на стороне сервера, в котором вам не понадобятся НИКАКИЕ пустые контейнеры:

<ul id="scheduler-loadroutegroups" class="full-height">
    {{#developers}}
        <ul>
            {{#pets}}
                <li>{{name}}</li>
            {{/pets}}
        </ul>
    {{/developers}}
</ul>

В этом случае, скажем, разработчики представляют набор моделей, а питомцы представляют набор моделей. Каждому из них потребуется собственное представление/подпредставление с прикрепленными к ним событиями.

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

Все примеры/документация Backbone, которые я видел, используют этот шаблон "пустой контейнер/дополнение". Возможно ли поступить иначе? Почему или почему бы и нет?


person J. Ky Marsh    schedule 01.02.2013    source источник
comment
В какой-то момент его нужно будет присоединить к DOM, но вам необходимо делать это в методе рендеринга (имейте в виду, что ваш el не обязательно должен быть существующим элементом) .   -  person Jack    schedule 01.02.2013
comment
Я думаю, нам нужно уточнить, что означает присоединение к DOM. Если бы весь шаблон был предварительно обработан (в том смысле, что не было пустых контейнеров), я думаю, вы могли бы прикрепить представление к определенной части DOM, используя .setElement()?   -  person J. Ky Marsh    schedule 01.02.2013
comment
Не совсем так, setEelement изменит el представления на новый элемент (повторно делегируя хеш событий), но вы можете в любой момент вставить его в какой-нибудь элемент DOM (в том числе просто прикрепить его к телу (чего вы, вероятно, не захотите делать)).   -  person Jack    schedule 01.02.2013
comment
Но если вся логика шаблона уже находится в (родительском) шаблоне, который предположительно уже отрендерен и сброшен в DOM, шаг вставки в DOM пропускается для всех дочерних элементов (таких как разработчики и домашние животные в моем примере), это не?   -  person J. Ky Marsh    schedule 01.02.2013
comment
Я не уверен, что понимаю, что именно вы имеете в виду, вы можете полностью отобразить родительский шаблон (включая всех дочерних элементов), а затем просто сбросить его в DOM, любые будущие визуализированные дочерние элементы могут быть затем просто вставлены в родительский элемент, который в этот момент уже находится в DOM.   -  person Jack    schedule 01.02.2013
comment
Правильно, мне интересно, когда родитель и ВСЕ дети отображаются одновременно, т.е. нет будущих визуализированных детей. Родительский шаблон, содержащий все дочерние шаблоны, визуализируется и добавляется в DOM, а затем будет вызываться setElement() для присоединения представления к дочернему шаблону (который уже находится в DOM) постфактум.   -  person J. Ky Marsh    schedule 02.02.2013


Ответы (1)


Представление Backbone требует элемента DOM и доходит до предоставления атрибутов для облегчения его создания, но ничто не заставляет вас использовать механизм шаблонов или манипуляции с DOM. Вы можете использовать существующую структуру разметки, вам просто нужно прикрепить представления к правильным узлам DOM.

Предполагая, что визуализированный HTML выглядит так

<ul id='scheduler-loadroutegroups'>
    <li id='d1'>
    <ul>
        <li id='p1'>P1</li>
        <li id='p2'>P2</li>
    </ul>
    </li>
    <li id='d2'>
    <ul>
        <li id='p3'>P3</li>
        <li id='p4'>P4</li>
    </ul>
    </li>
</ul>

вы можете использовать представление, которое захватывает соответствующие узлы DOM и связывает подпредставления. Сами подпредставления настраивают свои узлы DOM и так далее.

var DevListView = Backbone.View.extend({
    initialize: function() {
        this.inject();
    },

    inject: function() {
        var $el = this.$el;

        this.collection.each(function (model) {
            var subview = new DevView({
                el: $el.find("#d" + model.id),
                model: model
            });
        });
    }
});

var DevView = Backbone.View.extend({
    initialize: function() {
        this.inject();
    },

    inject: function() {
        var $el = this.$el;

        this.model.pets.each(function (model) {
            var subview = new PetView({
                el: $el.find("#p" + model.id),
                model: model
            });
        });
    }
});

var PetView = Backbone.View.extend({
    events: {
        'click ': function () {
            this.$el.toggleClass('selected');

            var msg = '<p>Pet '+this.model.get('id')+'</p>';
            $('body').append(msg);
        }
    }
});

Затем вы вызываете корневое представление с соответствующими данными, а методы инициализации делают все остальное.

var Developer = Backbone.Model.extend({
    initialize: function () {
        this.pets = new Backbone.Collection(this.get('pets'));
    },
    parse: function (data) {
        this.pets.reset(data.pets);
        return data;
    }
});
var Developers = Backbone.Collection.extend({
    model: Developer
});
var v = new DevListView({
    el: '#scheduler-loadroutegroups',
    collection: devs
});

См. http://jsfiddle.net/3xNHj/ для демонстрации.

Конечно, вы можете пойти дальше и перерисовать свои взгляды, эти вопросы могут помочь вам копать дальше.

Магистраль, а не оболочка this.el
Проблемы рендеринга BackboneJS

person nikoshr    schedule 02.02.2013
comment
Очень интересно, большое спасибо. Из любопытства, видите ли вы какие-либо преимущества или недостатки присоединения представлений к существующей структуре DOM по сравнению с созданием структуры/представлений полностью «на лету»? - person J. Ky Marsh; 05.02.2013
comment
@ J.KyMarsh Прогрессивное улучшение, SEO и загрузка приложений будут в столбце преимуществ, а рендеринг с двойным клиентом / сервером - в недостатках. И прямое манипулирование DOM, вероятно, легче понять или поддерживать. - person nikoshr; 05.02.2013