将数据从一个Backbone视图传递到另一个

假设我有以下Backbone视图,它加载两个链接,一个带有锚文本“test1”,另一个带有锚文本“test2”。

我绑定了一个click事件,我得到了被点击的链接的HTML,并将其存储在clickedHtml变量中。

现在,此视图由Backbone路由器加载。

当用户单击两个链接(test1或test2)中的任何一个时,路由器将加载另一个名为“main”的视图。

现在,我如何将“clickedHtml”变量传递给该视图?

我应该使用LocalStorage吗?

我应该像window.clickedHtml一样全局声明吗?

有没有更好的办法?

泰!

// file: views/test.js define([ 'jquery', 'underscore', 'backbone' ], function($, _, Backbone) { var Test = Backbone.View.extend({ el : '.test', initialize : function () { var that = this; that.$el.html('test1
test2'); }, events : { 'click .test a' : 'click' }, click : function (e) { var clickedHtml = $(e.target).html(); } return Test; });

这是我的路由器:

 // file: router.js define([ 'jquery', 'underscore', 'backbone', 'views/test', 'views/main' ], function ($, _, Backbone, Test, Main) { var Router = Backbone.Router.extend({ routes: { '' : 'home', 'test' : 'test' } }); var initialize = function () { var router = new Router(); router.on('route:home', function () { var main = new Main(); }); router.on('route:test', function () { var test = new Test(); }); Backbone.history.start(); } return { initialize : initialize } }); 

基本上你应该使用Backbone.Event :(或它在Marionette中的等价物)

 //Declaration var notificationService = {}; _.extend(notificationService, Backbone.Events); //Used by listener notificationService.on("alert", function(o) { alert(o); }); //Used by publisher notificationService.trigger("alert", {foo:"bar"}); 

真正的问题是它如何从一个视图传递到另一个视图?

我看到它的方式,你有两个选择:

  1. 初始化时,bubble notificationService从一个视图到另一个视图
  2. 使用返回它的requirejs模型包装notificationService(创建一个可以由requirejs传递的’几乎全局’的notificationService)。

虽然我不喜欢单身,但这种情况下,一个单独的notificationService对象可以很容易地被每个模型中的requirejs注入,这将派上用场。

编辑

另一个选项, 快速和脏 ,只需使用jquery触发DOM上的事件(特别是body元素)并在另一个视图中监听body

  //on Listening view, after DOM is ready $( "body" ).on( "alert", function( event, param1, param2 ) { alert( param1 + "\n" + param2 ); }); //on Triggering view, after DOM is ready $( "body").trigger( "alert", [ "Custom", "Event" ] ); 

注意

请注意,一旦监听视图关闭,它必须将自己从事件中取消(解除绑定/关闭),因此您不会有内存泄漏

从架构上讲,您的目标应该是保持代码的通用性和可重用性。

在这种情况下你不想做的主要事情之一是将直接引用从一个对象传递到另一个对象 – 如果你最终改变其中一个对象的设置,或者你需要从另一个对象传递数据同样,这可能会很快变得凌乱。

在这种情况下广泛使用的一种设计模式是中介。 也称为“pub / sub”,您可以拥有一个集中的独立对象,用于在对象之间调解信息。 某些对象将发布信息,其他对象可以订阅它们。 调解器充当中介,以便对象永远不必彼此直接通信。 这使得更通用,可重用和可维护的解决方案成为可能。

更多信息:

http://addyosmani.com/largescalejavascript/#mediatorpattern

Javascript模式

在骨干方面……如果您使用过Marionette,您可能会遇到一个名为wreqr的免费迷你图书馆(也由Derick Bailey实施)。 您可以使用它在Backbone应用程序中创建一个具有低开销的简单介体。

https://github.com/marionettejs/backbone.wreqr

它基本上允许您跨对象使用骨干样式事件。 示例如下:

首先,您需要创建一个全局可访问的中介对象,或将其添加到您的应用程序命名空间或使用require.js:

 var mediator = new Wreqr.EventAggregator(); 

在视图#1中

 events : { 'click .test a' : 'click' }, click : function (e) { var clickedHtml = $(e.target).html(); // trigger an 'element:click' event, which can be listened to from other // places in your application. pass var clickedHtml with the event // (passed to the arguments in your eventhandler function). mediator.trigger('element:click', clickedHtml); } 

内部视图#2

 initialize: function(){ //... this.listenTo(mediator, 'element:click', this.myEventHandler, this); } myEventHandler: function(elem){ // elem = clickedHtml, passed through the event aggregator // do something with elem... } 

骨干事件是这里的方式。 当您在视图中捕获事件时,我会使用以下命令将其冒泡:

 click : function (e) { var clickedHtml = $(e.target).html(); Backbone.Events.trigger("eventname",clickedHtml); } 

然后,您应该能够在路由器初始化函数中捕获它,使用:

 Backbone.Events.on("eventname", responseFunction); // listen out for this event 

然后在路由器中声明一个单独的函数:

 responseFunction : function(clickedHtml) { //Do whatever you want here } 

我是从记忆中写的,所以希望它有意义。 我也没有测试过像路由器这样的事件,但它应该可以工作。

HTH。

在你概述的确切情况下,我将在你的全局命名空间创建一个临时存储对象,并使用它来在你的视图之间传输数据,它有点“hacky”但比使用本地存储更好,或者直接使用window对象,至少在您自己的全局命名空间中使用临时对象时,已知对象使用的意图。

我觉得最好使用http://backbonejs.org/#Events来实现在两个视图之间传递数据的类似目的,尽管它确实取决于你如何构建页面,如果你在页面上有两个视图代表“控制“或”组件“这种方法非常有效。

如果你发布了一个链接到你的网站或我可以看看的东西,并给你一些帮助。

拉斯

您可以将其存储为视图中的属性:

 click : function (e) { this.clickedHtml = $(e.target).html(); } 

如果您的路由器可以访问两个视图,那么它可以简单地将firstView.clickedHtml属性传递给secondView (或初始化程序)中的函数