Передача аргументов в представление магистрали

Только начал работать с Backbone. У меня есть общий вид, который может отображать коллекцию в виде списка с заголовком. В настоящее время я передаю коллекцию и заголовок в метод рендеринга, но это кажется немного странным. Есть ли другой способ, более каноничный?

E.g.:

var ListView = Backbone.View.extend({
    template: _.template([
        "<div>",
        "<% if (title) { %><h2><%= title %></h2> <% } %>",
        "<% if (items.length > 0) { %>",
        "<ul>",
            "<% items.each(function(item) { %>",
            "<%= itemTemplate(item) %>",
            "<% }); %>",
        "</ul>",
        "<% } else { %><p>None.</p><% } %>",
        "</div>"
    ].join('')),

    itemTemplate: _.template(
        "<li><%= attributes.name %> (<%= id %>)</li>"
    ),

    render: function(items, title) {
        var html = this.template({
            items: items /* a collection */,
            title : title || '',
            itemTemplate: this.itemTemplate
        });

        $(this.el).append(html);
    }
});

var myView = new ListView({ el: $('#target') });
myView.render(myThings, 'My Things');
myView.render(otherThings, 'Other Things');

person sprugman    schedule 09.07.2012    source источник


Ответы (2)


Вы должны передать атрибуты в функцию initialize():

initialize: function (attrs) {
    this.options = attrs;
}

Итак, здесь вы должны передать атрибуты как объект, например:

new MyView({
  some: "something",
  that: "something else"
})

Теперь у вас есть значения, которые вы передали, доступные в этом экземпляре, в this.options

console.log(this.options.some) # "something"
console.log(this.options.that) # "something else"

Чтобы передать коллекцию, я рекомендую сделать одно родительское представление и одно подпредставление:

var View;
var Subview;

View = Backbone.View.extend({
    initialize: function() {
        try {
            if (!(this.collection instanceof Backbone.Collection)) {
                throw new typeError("this.collection not instanceof Backbone.Collection")
            }
            this.subViews = [];
            this.collection.forEach(function (model) {
                this.subViews.push(new SubView({model: model}));
            });
        } catch (e) {
            console.error(e)
        }
    },
    render: function() {
        this.subViews.forEach(function (view) {
            this.$el.append(view.render().$el);
        }, this);
        return this;
    }
});

SubView = Backbone.View.extend({
    initialize: function () {
        try {
            if (!(this.model instanceof Backbone.model)) {
                throw new typeError("this.collection not instanceof Backbone.Collection")
            }
        } catch (e) {
            console.error(e);
        }
    },
    render: function () {
        return this;
    }
});

testCollection = new MyCollection();
collectionView = new View({collection: testCollection});
$("body").html(collectionView.render().$el);

Вы должны всегда обрабатывать модели коллекции, а не только данные коллекции.

person Austin    schedule 09.07.2012
comment
Я предполагаю, что при таком подходе я создаю новое представление для каждой коллекции, а не повторно использую одно и то же представление с несколькими коллекциями. Имеет смысл. - person sprugman; 10.07.2012
comment
На самом деле ... если я просто передаю некоторые параметры при создании экземпляра, я не думаю, что мне даже нужно создавать метод инициализации - он автоматически помещает параметры, переданные конструктору, в объект параметров. - person sprugman; 10.07.2012
comment
И затем, если я не хочу создавать новое представление для каждой коллекции, я могу сделать myViewInstance.options.some = 'New Value'... - person sprugman; 10.07.2012
comment
Этот метод предназначен для передачи опций, не более того. Если вы передаете коллекцию, более эффективно создать одно представление для самой коллекции и подпредставление для каждой модели в этой коллекции. - person Austin; 10.07.2012
comment
Я добавил к ответу, как вы должны обращаться с коллекциями и их представлениями. - person Austin; 10.07.2012
comment
Я в замешательстве: почему вы строите представления из Backbone.Model, а не из Backbone.View? - person sprugman; 10.07.2012
comment
Опечатка, предполагалось использовать Backbone.View - person Austin; 10.07.2012
comment
Хорошо, это имеет больше смысла. Создание целого класса subView только для отображения ‹li›item.name‹/li› кажется мне излишним, но я понимаю, к чему вы клоните, и это, безусловно, имеет смысл для более сложного случая. - person sprugman; 10.07.2012
comment
Поверьте мне, это самый эффективный способ создания представлений для коллекций. Таким образом, вы можете делегировать объект events модели SubView для этой модели. Для каждого динамического представления всегда должна быть модель. - person Austin; 10.07.2012

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

var myModel = new Backbone.Model();

myModel.set("myThings", myThings);
myModel.set("myOtherThings", myOtherThings);

var myView = new ListView({ model: myModel });
person algiecas    schedule 09.07.2012
comment
Это вид коллекции моделей. Я полагаю, что у меня могла бы быть модель-обертка вокруг коллекции, но это кажется ненужной структурой. - person sprugman; 10.07.2012
comment
Вы можете передать модель и коллекцию одновременно. - person algiecas; 10.07.2012
comment
как получить доступ к модели внутри представления. Это эта.модель. Я спрашиваю об этом, потому что, например, если я передам: ListView({soption:true,model:myModel}), то я смогу получить доступ к опциону, используя: this.options.soption, но тогда модель также будет доступна с помощью this.options... .? - person user1102171; 12.09.2013
comment
Отвечая на мои собственные комментарии: доступ к модели можно получить с помощью this.options.model внутри основного представления. - person user1102171; 12.09.2013