主干事件总线和同一页面上的多个视图

use*_*236 1 javascript jquery events backbone.js backbone-events

我遇到了一个问题,我尝试使用一个简单的主干事件总线

var eventBus = _.extend({}, Backbone.Events);
Run Code Online (Sandbox Code Playgroud)

我在 DOM 中的多个视图下方有一个按钮,这些按钮是另一个视图,如下所示:

===================
===== CONTENT =====  <- VIEW 1 (content)
===================
BTN1 | BTN2 | BTN3   <- VIEW 2 (controls)
Run Code Online (Sandbox Code Playgroud)

这在一页上重复多次。

问题是,当我触发一个事件时,它会为页面上的所有视图触发。

在“控制”中,我有:

events: {
    'click .check': 'checkMe',
}

checkMe: function(e) {
    e.preventDefault();
    eventBus.trigger('checkMe');
}
Run Code Online (Sandbox Code Playgroud)

并且在所有视图中:

initialize: function(options) {
    …
    eventBus.on('checkMe', this.checkMe, this);
},

checkMe: function() {
    alert("!");
}
Run Code Online (Sandbox Code Playgroud)

正如我之前所说,当我单击一组按钮时,它会为页面上的每个视图(内容)触发事件,有没有办法让它以正确的方式工作?

谢谢你们!

bej*_*bee 5

我想到了一些选择。


你可以命名你的 events。如果每个视图都有一个唯一的 id,你可以像这样连接事件:

eventBus.trigger('checkMe:' + uniqueId);
Run Code Online (Sandbox Code Playgroud)

后来在视图中像这样捕捉它

eventBus.on('checkMe:' + this.id, this.checkMe, this);
Run Code Online (Sandbox Code Playgroud)

或者您可以使用 uniqueId 作为参数触发事件

eventBus.trigger('checkMe', {id: uniqueId});
Run Code Online (Sandbox Code Playgroud)

像这样处理事件:

checkMe: function(params) {
    if(params.id === this.id) {
        alert("!");
    }
}
Run Code Online (Sandbox Code Playgroud)

第三种选择可能是创建一个控制器对象来在每组内容和控件之间进行调解。控制器将充当事件总线,每个控制器都离散地处理控制器事件,从而防止全局事件问题。

---------------------------------------------
| ===================                       |
| ===== CONTENT =====  <- VIEW 1 (content)  | <- Controller Instance
| ===================                       |
| BTN1 | BTN2 | BTN3   <- VIEW 2 (controls) |
---------------------------------------------
Run Code Online (Sandbox Code Playgroud)

假设您有一个集合,您可以对其进行迭代以创建内容/控制集。它看起来像这样(以非常粗略的形式。)这里的控制器只是一个事件总线,但可以根据需要容纳更多逻辑。

collection.each(function(item) {
    var controller = _.extend({}, Backbone.Events);
    controller.onCheckMe = function () {
      contentView.performWork();
    };

    var contentView = new ContentView({
        performWork: function () {
            // TODO: do work here
        }
    });

    var controlsView = new ControlsView({
        events: {
            'click .check': 'checkMe',
        },
        checkMe: function(e) {
            e.preventDefault();
            this.trigger('checkMe');
        }
    );

    controller.listenTo(controlsView, 'checkme', controller.onCheckMe.bind(controller));

    // TODO: render the views here
});
Run Code Online (Sandbox Code Playgroud)