0

私が抱えている問題は、クリックイベントが積み重なっていくことです(ビューを変更した後もまだ接続されています)。ビューのインスタンスを 1 つだけにすることで問題を解決しました (以下を参照)。マークアップが変更されると、バックボーンはイベントを取り除くと思いました。他のビューではこの問題はありませんでした。

壊れたコード: ビューが作成されるにつれて、クリック イベントが loadPlayerCard に積み重なっていきます。

//Player Thumb View
PgaPlayersApp.PlayerThumbView = Backbone.View.extend({
    events: {
        'click': 'loadPlayerCard'
    },
    tagName: 'li',
    template: _.template( $('#player_thumb').html()),    
    render: function()
    {
        this.$el.html(this.template(this.model.toJSON()));
        return this;
    },
    loadPlayerCard: function()
    {
        new PlayerCardView({model: this.model}).render();
        return false;
    }
});

//Router
var Router = Backbone.Router.extend({
    routes:{
      '': 'loadPlayers'
    },

    loadPlayers: function()
    {
        PgaPlayersApp.Players.fetch({reset: true, success: function()
        {
            //When players is first fetched, we want to render the first player into the card area
            new PlayerCardView({model: PgaPlayersApp.Players.first()}).render();

        }});
    }
});

PgaPlayersApp.Router = new Router();
Backbone.history.start();

修正コード: 問題を修正するコード:

PgaPlayersApp.CurrentPlayerCard = new PlayerCardView();

//Player Thumb View
PgaPlayersApp.PlayerThumbView = Backbone.View.extend({
    events: {
        'click': 'loadPlayerCard'
    },
    tagName: 'li',
    template: _.template( $('#player_thumb').html()),    
    render: function()
    {
        this.$el.html(this.template(this.model.toJSON()));
        return this;
    },
    loadPlayerCard: function()
    {
        PgaPlayersApp.CurrentPlayerCard.model = this.model;
        PgaPlayersApp.CurrentPlayerCard.render();
        return false;
    }
});

//Router
var Router = Backbone.Router.extend({
    routes:{
      '': 'loadPlayers'
    },

    loadPlayers: function()
    {
        PgaPlayersApp.Players.fetch({reset: true, success: function()
        {
            //When players is first fetched, we want to render the first player into the card area
            PgaPlayersApp.CurrentPlayerCard.model = PgaPlayersApp.Players.first();
            PgaPlayersApp.CurrentPlayerCard.render();
        }});
    }
});

PgaPlayersApp.Router = new Router();
Backbone.history.start();

PlayerCardView (参照用):

var PlayerCardView = PgaPlayersApp.PlayerCardView = Backbone.View.extend({
    events: {
        'click': 'flipCard'
    },
    el: '#pga_player_card',
    template: _.template( $('#player_card').html()),
    render: function()
    {
        this.$el.html(this.template(this.model.toJSON()));
        return this;
    },
    flipCard: function()
    {
        this.$("#player_card_container").toggleClass('flip');
    }
});
4

1 に答える 1

0

ルーターでは、新しいPlayerCardViewsを作成し続けます。

new PlayerCardView({model: PgaPlayersApp.Players.first()}).render();

これらのビューはすべて、まったく同じものを共有していますel

el: '#pga_player_card'

したがって、新しい を作成し続けPlayerCardView、それぞれが にバインドし#pga_player_cardます。

これを行うたびに、新しいビューをまったく同じ DOM 要素にバインドし、それらのビューのそれぞれが呼び出しdelegateEventsてイベント ハンドラーをバインドします。jQuery のメソッドdelegateEventsにバインドすることにel注意してください。html

子要素からデータやイベント ハンドラーなどの他の構成要素を削除してから、それらの要素を新しいコンテンツに置き換えます。

htmlもしませんが、子要素elからイベント ハンドラーを削除します。次の簡単な例を考えてみましょう:<div id="d"></div>

$('#d').on('click', function() {
    console.log('Before .html');
});
$('#d').html('<p>Where is pancakes house?</p>');
$('#d').on('click', function() {
    console.log('After .html');
});

次に をクリックする#dと、コンソールに前後のメッセージが表示されます。

デモ: http://jsfiddle.net/ambiguous/ftJtS/

その単純な例は、多かれ少なかれ、あなたがしていることと同等です。

次の場合は、より快適に過ごすことができます。

  1. ビューを内側 に置き、#pga_player_cardルーターに任せます$('#pga_player_card').append(view.render().el)
  2. view.remove()新しいビューを追加する前に、既存のビューとそれを追跡します。

複数のビュー インスタンスに対して DOM 要素を再利用しようとしたり、ビューを再利用しようとしたりすることは避けてください。どちらも手間をかける価値はありません。

于 2013-06-14T18:04:42.280 に答える