Nodejs backbonejs 视图事件重复执行

Nodejs backbonejs 视图事件重复执行

我有2个视图,分别是显示不同的列表。但是在切换列表的时候,在点击列表下面的分页按钮出现重复请求服务器的地址,并且重复请求的次数是随着我切换两个视图的次数来不断增加的。不知道是什么原因。如果是单个视图的时候,请求是正常的。有谁对backbonejs比较熟悉的吗? 还是我程序本身有问题。 第一次切换视图: GET /Pictures/:PageSize/:PageIndex?PageSize=20&PageIndex=3 200 14ms GET /Pictures/:PageSize/:PageIndex?PageSize=20&PageIndex=3 200 17ms

第二次切换视图: GET /Pictures/:PageSize/:PageIndex?PageSize=20&PageIndex=3 200 14ms GET /Pictures/:PageSize/:PageIndex?PageSize=20&PageIndex=3 200 17ms GET /Pictures/:PageSize/:PageIndex?PageSize=20&PageIndex=3 200 18ms


6 回复

Node.js & Backbone.js 视图事件重复执行问题

问题描述

你提到在使用Backbone.js时遇到一个问题:当你在两个不同的视图之间切换时,点击分页按钮会导致重复请求服务器,而且请求的次数会随着视图切换的次数增加。

原因分析

这个问题通常是由于视图被多次初始化,导致事件绑定多次。每次初始化视图时,事件监听器都会被重新绑定到元素上,而不会被移除或替换。因此,当用户在不同视图间切换并再次点击分页按钮时,事件处理函数会被多次触发,从而导致多次请求服务器。

解决方案

为了确保事件只被绑定一次,可以在视图中使用remove方法来清理事件监听器。Backbone.js提供了undelegateEvents方法来解除所有事件绑定,但通常更好的做法是在视图销毁时进行清理。

以下是一个示例代码,展示了如何在视图销毁时清理事件:

var ListView = Backbone.View.extend({
    el: '#list-container',
    events: {
        'click .pagination-button': 'loadMore'
    },
    initialize: function() {
        this.listenTo(this.collection, 'reset', this.render);
    },
    render: function() {
        // 渲染视图逻辑
        return this;
    },
    loadMore: function(event) {
        event.preventDefault();
        var pageSize = 20;
        var pageIndex = this.$('.pagination-button').data('page-index');
        // 发送请求到服务器
        $.get(`/Pictures/${pageSize}/${pageIndex}`, function(data) {
            console.log(data);
        });
    },
    remove: function() {
        // 清理事件监听器
        this.undelegateEvents();
        Backbone.View.prototype.remove.call(this);
    }
});

// 使用视图
var listView = new ListView({ collection: yourCollection });
listView.render();

// 切换视图时销毁当前视图
listView.remove();

示例解释

  1. 事件绑定:在events对象中定义了点击分页按钮的事件处理器。
  2. 初始化:在initialize方法中监听集合的reset事件,以便在数据更新时重新渲染视图。
  3. 加载更多数据loadMore方法用于处理分页按钮的点击事件,发送请求到服务器。
  4. 清理事件:在remove方法中调用this.undelegateEvents()来移除所有事件绑定,并调用父类的remove方法来清理视图。

通过这种方式,当视图被销毁时,所有的事件监听器也会被移除,避免了事件重复绑定的问题。


很明显,视图没有得到正常消除,事件一直在重复绑定

试试这个,把你之前绑定的都取消掉。需要这个view的时候再绑定。 undelegateEvents() Removes all of the view’s delegated events. Useful if you want to disable or remove a view from the DOM temporarily.

backbone的view 里有个remove的方法 view.remove() Removes a view from the DOM, and calls stopListening to remove any bound events that the view has listenTo’d.

因为你把事件重复绑定在同一节点上了,所以每次new视图的时候都会重新绑定事件。

这个问题通常是由于视图没有正确地解绑或重置事件导致的。每次切换视图时,新的视图实例被创建,而旧的视图实例中的事件监听器仍然存在。这会导致事件监听器重复注册,从而导致事件重复触发。

以下是一个示例代码,展示了如何在Backbone视图中正确地解绑事件:

var ListView = Backbone.View.extend({
    initialize: function() {
        this.listenTo(this.collection, 'reset', this.render);
    },
    events: {
        'click .pagination-button': 'fetchPage'
    },
    fetchPage: function(e) {
        e.preventDefault();
        var pageIndex = $(e.target).data('page-index');
        this.collection.fetch({ data: { PageIndex: pageIndex } });
    },
    render: function() {
        // 渲染逻辑...
        return this;
    },
    close: function() {
        // 解绑所有事件监听器
        this.stopListening();
        // 如果需要,可以销毁视图元素
        this.remove();
    }
});

// 切换视图时调用close方法
function switchView(newView) {
    if (currentView) {
        currentView.close();
    }
    currentView = newView;
    $('#view-container').html(newView.render().el);
}

解释

  1. initialize: 在初始化时绑定事件监听器。
  2. events: 定义事件映射,当用户点击.pagination-button时触发fetchPage方法。
  3. fetchPage: 获取分页数据的方法。
  4. render: 视图渲染方法。
  5. close: 关闭视图时清理事件监听器和其他资源。确保每次切换视图时旧视图不会留下残留的事件监听器。
  6. switchView: 控制视图切换的方法,在切换视图时先关闭当前视图以清理其事件监听器。

这样可以避免事件重复绑定导致的重复请求问题。

回到顶部