1

私は Backbone.js の開発にかなり慣れていないため、サブビューをレンダリングしようとしているときに少し障害が発生しました。

現在、カスタム ドロップダウン ボタンやその他の要素をレンダリングするためのいくつかのビューを用意しています。DocumentCloud のコードに基づいてこのアプローチを採用しました

これが私がこれまでに持っているものです:

app.ui.SelectMenu = Backbone.View.extend({

    className: 'btn-group group-item',

    options: {
        id: null,
        standalone: false
    },

    events: {
        "click .dropdown-menu a": "setLabel"
    },

    constructor: function (options) {
        Backbone.View.call(this, options);

        this.items = [];
        this.content = JST['common-select_button'];
        this.itemsContainer = $('.dropdown-menu', $(this.content.render()));

        // Add any items that we may have added to the object params
        if (options.items) {
            this.addItems(options.items);
        }
    },

    render: function () {
        this.$el.html(this.content.render({
            label: this.options.label,
            items: this.itemsContainer
        }));
        this._label = this.$('.menu-label');
        return this;
    },

    setLabel: function (label) {
        $(this._label).text(label || this.options.label);
    },

    addItems: function (items) {
        this.items = this.items.concat(items);
        var elements = _(items).map(_.bind(function (item) {
            var attrs = item.attrs || {};
            _.extend(attrs, { 'class': 'menu_item' + (attrs['class'] || '') });

            var el = this.make('li', attrs, item.title);
            return el;
        }, this));

        $(this.itemsContainer).append(elements);
    }
});

これまでのところ、ボタンと適切なラベルを正常にレンダリングしましたが、関数 .dropdown-menuを呼び出すときにデータを入力できないようです。addItems

renderヒットしたとき、文字列ではなくjQueryオブジェクトを渡しているため、アイテム変数にデータを入力できないと想定していますが、使用するたびにitems: this.itemsContainer.html()、引用符で囲まれたhtmlを貼り付けるだけです...単純に置き換えることができます引用ですが、それは私にとってハックのように感じます.

どんな助けでも大歓迎です。ありがとう!

4

1 に答える 1

2

jQueryappendは配列を取りません:

.append( content [, content] )

content : 一致した要素のセット内の各要素の最後に挿入する DOM 要素、HTML 文字列、または jQuery オブジェクト。
content : 一致した要素のセット内の各要素の最後に挿入する 1 つ以上の追加の DOM 要素、要素の配列、HTML 文字列、または jQuery オブジェクト。

1 回の呼び出しで複数の要素を追加する場合は、それらを個別の引数として指定する必要があります。

$(x).append(e1, e2, e3, ...);

applyしたがって、配列を別の引数に変換するために使用する必要があります。

var $i = $(this.itemsContainer);
$i.append.apply($i, elements);

ただし、そのようなごまかしは実際には必要ありません。作成時に 1 つずつ追加できます。

addItems: function (items) {
    this.items = this.items.concat(items);
    _(items).each(function (item) {
        var attrs = item.attrs || {};
        _.extend(attrs, { 'class': 'menu_item' + (attrs['class'] || '') });

        this.itemsContainer.append(this.make('li', attrs, item.title));
    }, this);
}

また_.each、引数を取ることができるので、別の呼び出しcontextは必要ありません。_.bindそして、それはすでに jQuery オブジェクトであると確信しているthis.itemsContainerので、再度ラップする必要はありません$()

あなたにも問題があるかもしれませんrender

render: function () {
    this.$el.html(this.content.render({
        label: this.options.label,
        items: this.itemsContainer
    }));
    this._label = this.$('.menu-label');
    return this;
}

items: this.itemsContainerこれでstringifying が終了すると思われthis.itemsContainerますが、次のような方がうまくいく可能性があります。

this.$el.html(this.content.render({ label: this.options.label });
this.$el.find('some selector').append(this.itemsContainer);

もちろん、場所'some selector'は HTML 構造に依存します。これについてもテンプレートを調整する必要があります。


Github リンクが壊れているため、どのコードを適応させているのかわかりません。constructorの使用が非標準であることは知っています。なぜ標準を使用しないのinitializeですか?

コンストラクター/初期化 new View([options])

[...] ビューがinitialize関数を定義する場合、ビューが最初に作成されたときに呼び出されます。

おそらく次のようにする必要があります。

app.ui.SelectMenu = Backbone.View.extend({
    // No 'constructor' in here or anywhere...
    initialize: function (options) {
        this.items = [];
        this.content = JST['common-select_button'];
        this.itemsContainer = $('.dropdown-menu', $(this.content.render()));

        // Add any items that we may have added to the object params
        if (options.items) {
            this.addItems(options.items);
        }
    },
    //...
});
于 2012-06-28T02:55:28.450 に答える