8

我有一个带有多个backbone.js 视图的单页Web 应用程序。视图有时必须相互交流。两个例子:

  1. 当有两种方式的视图同时以不同的方式呈现集合时,必须将一个视图中的项目单击传递到另一个视图。
  2. 当用户转换到流程的下一阶段并且第一个视图将数据传递给第二个视图时。

为了尽可能地解耦视图,我目前使用自定义事件来传递数据($(document).trigger('customEvent', data))。有一个更好的方法吗?

4

3 回答 3

15

一种广泛使用的技术是扩展Backbone.Events-object 以创建您的个人全局事件聚合器。

var vent = {}; // or App.vent depending how you want to do this
_.extend(vent, Backbone.Events);

根据您使用的是 requirejs 还是其他东西,您可能希望将其分离到自己的模块中或使其成为 Application 对象的属性。现在,您可以在应用程序的任何位置触发和监听事件。

// View1
vent.trigger('some_event', data1, data2, data3, ...);

// View2
vent.on('some_event', this.reaction_to_some_event);

这也允许您使用事件聚合器在模型、集合、路由器等之间进行通信。这是 Martin Fowler 的事件聚合器概念(不是在 javascript 中)。这里有一个更主干的实现和对这个主题的反思,更像是 Backbone.Marionette 的脉络,但其中大部分适用于 vanilla Backbone。

希望这有帮助!

于 2012-07-23T10:02:48.400 回答
8

我在第一部分同意@jakee

var vent = {}; 
_.extend(vent, Backbone.Events);

但是,使用“on”监听全局事件可能会导致内存泄漏和僵尸视图问题,并且还会导致多个操作处理程序调用等。

您应该在视图中使用“listenTo”而不是“on”

 this.listenTo(vent, "someEvent", yourHandlerFunction);

因此,当您删除视图时view.remove(),此处理程序也将被删除,因为处理程序绑定到您的视图。

触发全局事件时,只需使用

vent.trigger("someEvent",parameters);
于 2014-05-25T00:32:43.737 回答
0

jakee 的回答提出了我自己使用过的一种很好的方法,但是还有另一种有趣的方法,那就是将一个对象的引用注入到每个视图实例中,而注入的对象又包含对尽可能多的视图的引用。总计的。

本质上,视图聚合器是一种“App”对象,可以附加视图之外的东西,例如集合。它确实涉及扩展视图,因此可能不符合每个人的口味,但另一方面,扩展是这样做的一个简单示例。

我使用http://arturadib.com/hello-backbonejs/docs/1.html上的代码作为我的 ListView 的基础,然后我得到了以下工作:

define(
    ['./listView'],

    function (ListView) {
        var APP = {
            VIEWS : {}
        }

        ListView.instantiator = ListView.extend({
            initialize : function() {
                this.app = APP;
                ListView.prototype.initialize.apply(this, arguments);
            }
        });

        APP.VIEWS.ListView = new ListView.instantiator();
        console.log(APP.VIEWS.ListView.app);
    }
);
于 2013-11-21T22:09:28.203 回答