3

カテゴリのツリーがあり、jQuery を使用する代わりに Backbone.js を使用してレンダリングを行うか、サーバー側でレンダリングを行いたいと考えています。テンプレートとして説明した次のブレークアウトがあります。

<li>
    <select class="categories">
        <option value="">Select</option>
    </select>
    <input class="edit" type="button" value="Edit">
    <input class="add" type="button" value="Add">
</li>

select内部ビューとして個別にレンダリングするタグ。select を変更するときは、入れ子になったカテゴリをサーバーから取得し、タグliでラップされた上記のテンプレートを使用してタグに追加する必要がありますul。外側のビューでは、内側のビューを作成し、編集および追加時にクリックしてイベントをリッスンします。ネストのレベルが複数の場合、ネストのレベルと同じ回数の火災であるため、最後のイベントに問題があります。私は何を間違っていますか?

以下のコード スニペットは、外部ビューと内部ビューの操作方法を示しています。

    var CategoriesInnerView = Backbone.View.extend({
        tagName:       'select',
        initialize:    function(){
            _.bindAll(this,'addOne','addAll');
            this.collection.bind('reset',this.addAll);
        },
        addOne:        function(category){
            this.$el.append(new CategoryView({model:category}).render().el);
        },
        addAll:        function(){
            this.collection.each(this.addOne);
        },
        events:        {
            'change':'changeSelected'
        },
        changeSelected:function(){
            var children = new Categories();
            children.url = 'categories/' + this.$el.val();

            var childrenView = new CategoriesOuterView({collection:children});
            this.$el.parent().find('ul').remove();
            this.$el.parent().append(childrenView.render().el);

            children.fetch();
        }
    });

    var CategoriesOuterView = Backbone.View.extend({
        tagName:   'ul',
        template:  _.template($('#categories-template').html()),
        initialize:function(){
            this.inner = new CategoriesInnerView({collection:this.collection});
        },
        render:    function(){
            this.$el.html(this.template);

            this.inner.setElement(this.$('select')).render();

            return this;
        },
        events:    {
            'click .edit':'edit',
            'click .add': 'add'
        },
        edit:    function(){
            this.renderForm(this.collection.get(this.inner.$el.val()));
        },
        add:    function(){
            this.renderForm(new Category());
        },
        renderForm:function(category){
            // some code to render the form
        }
    });
4

2 に答える 2

3

ネストされたビューをセットアップするときは、イベントが DOM ツリーをバブルアップし、Backbone が view.el レベルで DOM イベントを処理するという事実を考慮する必要があります。つまり、このシナリオでは、ネストされたノードは、イベントを階層の上に移動させると、親ノードでもイベントをトリガーします。

デモについては、http://jsfiddle.net/PX2PL/を参照してください。

簡単な解決策は、コールバックでイベントの伝播を停止することです

var CategoriesOuterView = Backbone.View.extend({
    events:    {
        'click .edit':'edit',
        'click .add': 'add'
    },
    edit: function(e) {
        e.stopPropagation();
        this.renderForm(this.collection.get(this.inner.$el.val()));
    },
    add: function(e) {
        e.stopPropagation();
        this.renderForm(new Category());
    }
}

更新されたデモhttp://jsfiddle.net/PX2PL/1/

于 2012-12-29T12:28:22.510 に答える
2

これに適切に答えるには、実際にコードの一部を確認する必要がありますが、次の 2 つのいずれかが発生しているようです。

1)同じ要素でビューを複数回インスタンス化しています

2) イベント セレクターが広すぎる

しかし、ビュー (の関連部分) を実際に見なければ、それ以上のことを言うのは困難です。


接線関連の補足事項

ところで、あなたがこのようなものを持っているとき、あなたが取ることができる2つの基本的なアプローチがあります:

1)親ビューにサブビューを作成させ、サブビューにイベント処理を配置できます

2)親ビューにサブビューを作成させるか、作成させないか(すべてのHTML自体を作成できます)、それにイベント処理を配置できます。

#1 の利点は単純さです。イベント ハンドラーthisは関連するビューを参照するだけで済みます。ただし、スケールアップしすぎる必要がある場合、#1 には問題があります。それぞれ独自のイベント ハンドラーを持つ数百万のビューは、パフォーマンスを低下させます。

したがって、パフォーマンスが重要である場合は、イベント フックアップのセットを 1 つしか実行していないため、#2 の方が優れています。ただし、イベント ハンドラーは、提供されたイベントに基づいてどの要素で動作しているかを把握する必要があるため、よりスマートにする必要があります (つまり、#1 のアプローチと比較して) e.targetthis

于 2012-12-28T21:05:53.027 に答える