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

时间:2013-11-25 23:34:34

标签: javascript jquery backbone.js

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

我绑定了一个点击事件,我获得了点击链接的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('<a href="#/main">test1</a><br /><a href="#/main">test2</a>');


                    },

                    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 
        }
    });

5 个答案:

答案 0 :(得分:4)

基本上你应该使用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. 初始化
  2. 中的bubble notificationService从一个视图到另一个视图
  3. 使用返回它的requirejs模型包装notificationService(创建一个可以由requirejs传递的'几乎全局'的notificationService。)
  4. 虽然我不喜欢单身,但这种情况下,一个单独的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" ] );
    

    注意

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

答案 1 :(得分:4)

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

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

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

更多信息:

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

Javascript Patterns

在Backbone方面......如果您使用过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...
}

答案 2 :(得分:1)

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

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。

答案 3 :(得分:0)

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

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

如果您发布了指向您网站的链接或其他内容,我可以查看并为您提供更多帮助。

拉​​斯

答案 4 :(得分:-1)

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

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

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