itemView触发到达parrent的自定义事件

时间:2013-08-19 08:29:13

标签: javascript layout triggers marionette event-bubbling

我有这个代码 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

3 个答案:

答案 0 :(得分:8)

我找到了解决方案(隐藏在文档中的某处,在布局,区域和视图之间建立了一些连接)!

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


在父(布局)和子(itemView)之间的通信 ONLY 的上下文中:

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


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

坚持不懈,任何事情都可以实现。

答案 1 :(得分: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一个本地backbone.Event扩展对象,因此两者之间的通信将是私有的。

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

答案 2 :(得分:0)

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

项目视图不是被点击的东西。你需要指定一个像这样的实际dom元素:

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

但是,如果你想听听赛道下方发生的事件,你应该坚持使用jquery on方法。无论在渲染此视图时生成的ui是什么,它都会侦听任何冒泡的内容

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