0

我遇到的问题是点击事件不断堆积(更改视图后仍然附加)。我通过只有一个视图实例(如下所示)解决了这个问题。我认为当标记改变时主干摆脱了事件。其他观点我没有这个问题。

损坏的代码:随着更多视图的创建,点击事件不断堆积在 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

在您的路由器中,您不断创建新PlayerCardView的 s:

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

所有这些观点都完全相同el

el: '#pga_player_card'

因此,您不断创建新PlayerCardView的 s 并且每个都绑定到#pga_player_card.

每次执行此操作时,都会将全新的视图绑定到完全相同的 DOM 元素,并且这些视图中的每一个都将调用delegateEvents绑定事件处理程序。请注意,delegateEvents绑定到eljQueryhtml方法

在用新内容替换这些元素之前,从子元素中删除其他构造,例如数据和事件处理程序。

所以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 回答