2

我有这个代码 http://jsfiddle.net/QRcF5/2/

$(function() {
    var Header = Backbone.Marionette.ItemView.extend({
        template: _.template('<h4>TEST</h4><button>EDIT</button>'),

        tagName: 'nav',

        triggers: {
            'click button': 'btn_clicked'
        }
    }),
    Layout = Backbone.Marionette.Layout.extend({
        template: _.template('<header></header>'),

        regions: {
            header: 'header'
        },

        events: {
            'itemview:btn_clicked': 'clicked'
        },

        clicked: function() {
            alert('Ana are mere');
        }
    });

    layout = new Layout();
    $('body').append(layout.render().el);
    layout.header.show(new Header());
});

我正在使用带有一个 ItemView 的布局(稍后我想要更复杂的嵌套)并希望在 LAYOUT 中捕获 ITEMVIEW 中发生的事件。似乎它没有向上冒泡,或者我在这里做错了什么。


更新 1 我已经尝试过事件、触发器(针对子级)和事件(针对父级),但我仍然无法在父级内部捕获事件。

我可以用:

_.extend(App.vent, Backbone.Events);

Backbone.Marionette.ItemView.extend({
    ....
    App.vent.trigger('btn_clicked');
    ....
});

Backbone.Marionette.Layout.extend({
    ....
    App.vent.on('btn_clicked', function() { doCoding(); });
    ....
});

但是这样我就打破了封装。有没有办法通过使用 Marionette 触发器事件来保持封装并将其全部保留在布局中而不污染整个应用程序?


更新 2

http://jsfiddle.net/QRcF5/5/

我已经更新了 jsfiddle 以使用 _.extend(vent, Backbone.Events)。如果有人对此有更好的模式,请告诉我们:D

4

3 回答 3

8

我找到了解决方案(埋在文档的某个地方,在布局、区域和视图之间建立了一些联系)!

http://jsfiddle.net/QRcF5/6/


在父级(布局)和子级(itemView)之间进行通信的情况下:

1)孩子触发自定义事件(与发泄扩展Backbone.Events相反-它只对有权访问它的人说话=封装)

triggers: {
    'click button': 'custom_event:btn_clicked'
}


2)父母可以通过on('show',....)来收听这个可以访问孩子的事件

initialize: function() {
    var that = this; // needed for the listenTo which overrides 'THIS'

    this.header.on('show', function(view) {
        this.listenTo(view, 'custom_event:btn_clicked', that.clicked);
    });
},


例子:

layout = new Layout();
$('body').append(layout.render().el);
layout.header.show(new Header()); // Here we get access to child and its events


木偶的(隐藏的)力量。(我的意思是当我说隐藏时,因为相对较新,文档是准系统,复杂的例子很少)。

只要有一点毅力,任何事情都可以完成。

于 2013-08-27T14:00:45.620 回答
1

您应该只返回 true 并让点击在 DOM 中冒泡,请参阅http://jsfiddle.net/aGaDY/

var Header = Backbone.Marionette.ItemView.extend({
  template: _.template('<h4>TEST</h4><button>EDIT</button>'),
  events: {
    'click button': 'btn'
  },
  btn: function () {
    return true;
  }
}),

Layout = Backbone.Marionette.Layout.extend({
    template: _.template('<div>Before:</div><header></header><div>After:</div><div class="body">Body Goes Here</div>'),
    regions: {
        header: 'header'
    },
    events: {
        'click': 'btn_clicked'
    },
    btn_clicked: function () {
        alert('Ana are mere');
    }
});
layout = new Layout();
$('body').append(layout.render().el);
layout.header.show(new Header());

您甚至可以完全删除 ItemView 上的事件处理,冒泡是默认行为

编辑

如果您希望能够区分不同的按钮单击并防止使用与应用程序无关的内部事件污染全局空间,我可以想到两个选项。

通过 jquery 数据函数和 event.target 移动事件目标上的数据:

// In Header
bth:function(e){
  $(e.target).data("source", "myButton")
}
// ....
// in the Layout 
btn_click: function(e){
  if ($(e.target).data("source") === "myButton") this.doSomething()
}

另一种选择是布局将向 Header 传递一个本地主干。事件扩展对象,因此两者之间的通信将是私有的。

我了解封装的问题,但我认为您建议的全局 App.Vent 的可读性会更好

于 2013-08-20T10:12:48.020 回答
0
events: {
            'itemview:btn': 'btn_clicked'
        },

itemview 不是被点击的东西。您需要像这样指定一个实际的 dom 元素:

events: {
            'click .someThingWithAClass': 'myFunction'
        },

但是,如果您想收听进一步发生的事件,您可能应该坚持使用 jqueryon方法。这将侦听任何冒泡的内容,而不管在呈现此视图时已生成的 ui

http://api.jquery.com/on/

于 2013-08-19T10:27:21.143 回答