【问题标题】:How to handle event bubbling?如何处理事件冒泡?
【发布时间】:2012-11-03 10:17:54
【问题描述】:

我正在开发一个小型主干应用程序。

我目前遇到的问题是我想显示特定项目的个人资料。

当我单击列表项时会触发此 showProfile 事件。不是 showProfile 事件需要通知父 listView 通知上面的 sidebarView 通知 mainView 现在可以实例化 profileView。

这将涉及事件链中的三到四个视图。有没有办法解决这个问题?

问候, 博多

【问题讨论】:

  • 如果只是停止事件冒泡的问题,您可以将event 对象传递给事件处理程序并调用event.stopPropagatoin() 以使其不冒泡。你也可以看看jQuery API
  • 你的意思是想让 showProfile 事件直接通知主视图,跳过中间的列表和侧边栏视图?
  • @Cyclone 我不是说 DOM 事件冒泡。我的意思是backbone.events事件系统
  • @MattiJohn 在具体情况下是的,我想从嵌套的嵌套视图访问我的应用程序路由器。在所有视图上冒泡路由器访问会导致大量锅炉代码只是为了冒泡而没有良好的功能......通过使用requirejs导入路由器直接使用路由器只会异步工作......

标签: javascript events backbone.js publish-subscribe event-bubbling


【解决方案1】:

我不知道这是否是最好的方法,但对于这种情况,我通过创建一个具有扩展 Backbone.Events 的事件属性的对象来使用应用程序级事件聚合器。

我也倾向于使用相同的对象来存储应用程序范围的设置:

var app = {
    settings: {},
    events: _.extend({}, Backbone.Events),
};

然后您可以从您的视图中触发一个 showProfile 事件并绑定到您的 mainView 中的 app.event,而无需通过所有父视图冒泡。

在使用 RequireJS 时,我创建了一个应用模块,它是我的视图的依赖项:

define([
    "jquery",
    "underscore",
    "backbone"
],

function($, _, Backbone) {
   var app = {
       root: "/",
       settings: {},
       events: _.extend({}, Backbone.Events),
   };

 return app;

});

我也倾向于将我的路由器放在 app 对象上,以防我需要在视图中访问它,所以在我的 main.js 中(如在 backbone-boilerplate 中):

require([
   "app",
   "router",
],

function(app, Router) {
    app.router = new Router();
    Backbone.history.start({ pushState: true, root: app.root });
});

您可能想阅读 Derick Bailey 关于事件聚合器的博文:

http://lostechies.com/derickbailey/2011/07/19/references-routing-and-the-event-aggregator-coordinating-views-in-backbone-js/

http://lostechies.com/derickbailey/2012/04/03/revisiting-the-backbone-event-aggregator-lessons-learned/

【讨论】:

  • 您好,谢谢您的回答。我认为事件聚合器很难耦合或导致新问题,我将继续使用事件冒泡,但我认为它可能对其他人有所帮助。问候
  • @muistooshort 谢谢,你说得对,我的意思是 _.extend({}, Backbone.Events)。现已修复。
【解决方案2】:

同意,这类事情涉及很多样板文件。我尝试过的一种方法是通过使用如下定义的(视图)方法来最小化这种情况:

/**
 * Helper to facilitate event-bubbling, that is to say, the scenario where a view
 * binds a callback to a child-View event only to retrigger it, mimicking the
 * inherent event bubbling mechanism of the DOM. Allows renaming of the bubbled
 * event as well as modification of the bubbled arguments
 *
 * @param view The View-dispatcher of the event
 * @param ev Name of the event to bubble
 * @param opts A hash of options where:
 *   bubbleName: New name of the event to bubble in case the event should be
 *   renamed. Optional
 *   args: The arguments to bubble:
 *    - When absent, the original arguments will be bubbled.
 *    - When set to a non-function value or an array-of-values, this value or
 *      values will be bubbled
 *    - When set to a function, it will be invoked on the incoming arguments and
 *      its returned value will be treated as in the previous case.
 */
bubbleEvent: function (view, ev, opts) {
  if (!opts) { opts = {}; }
  view.bind(ev, function () {
    var inArgs = _.toArray(arguments),
        bubbleArgs = _.isFunction(opts.args) ? 
          opts.args.apply(this, inArgs) : (opts.args || inArgs),
        bubbleName = opts.bubbleName || ev;
    this.trigger.apply(this, [bubbleName].concat(bubbleArgs));
  }, this);
}

这将是 BaseView 的成员函数,您的所有其他视图都将扩展它。因此,它将在应用程序的每个视图中都可用。因此,为了让 ParentView 简单地冒泡由拥有的 childView 触发的事件,您只需要

bubbleEvent(childView, "event");

不过,这引入了 一些 样板,所以我也有兴趣看到这个问题的其他解决方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-01
    • 1970-01-01
    • 2011-10-20
    • 2011-08-23
    • 1970-01-01
    相关资源
    最近更新 更多