2013-05-31 108 views
9

我有一个区域的布局视图,在该区域我有一个项目视图触发一个事件,但它似乎没有冒泡到布局视图。我做错了什么或者是这种设计的行为?我认为itemview前缀不会被添加,因为父视图不是一个集合视图?无论哪种方式,事件从不冒泡到布局视图。从itemview到父布局视图的木偶气泡事件?

layoutView = Marionette.Layout.extend({ 
     template: "#layout-template", 
     regions: { 
      titleRegion: "#job-title-region" 
     }, 
     triggers: { 
      "save:clicked" : "onSaveClicked" 
     }, 
     onSaveClicked: function (args) { 
      alert('Clicked'); 
     } 
    }); 

childview = Marionette.ItemView.extend({ 
     template: "#child-template", 
     triggers: { 
      "click .js-save": "save:clicked" 
     } 
    }); 

UPDATE:

看到这个小提琴http://jsfiddle.net/7ATMz/11/我设法布局来看倾听孩子的事件,但我必须连线它的布局视图本身之外,打破封装。我可以在布局视图中执行此操作吗?

感谢,

乔恩

回答

0

为什么不干脆让click事件冒泡的DOM层次结构和布局视图处理呢?像这样的东西(小提琴here):

var MainView = Marionette.Layout.extend({ 
    template: "#layout-template", 
    regions: { 
     childRegion: "#childRegion" 
    }, 
    events: { 
     'click #btn': 'handleButtonClick' 
    }, 
    handleButtonClick: function() { 
     alert('btn clicked in child region and bubbled up to layout'); 
    } 
}); 

var ChildView = Marionette.ItemView.extend({ 
    template: "#child-template" 
    /* 
    triggers: { 
     "click #btn": "btn:clicked" 
    }*/ 
}); 
+0

这个如果我从布局子区域中的视图中引发事件,似乎不起作用? – Jon

+0

对不起,这确实是一个猜测。点击事件应该会将DOM层次结构膨胀到布局视图,所以您应该能够使用通常的事件对象在布局中捕获它。 –

+0

你能把一个简单的http://jsfiddle.net例子放在一起吗? –

10

触发器不那么回事:你的布局正在使用他们错了。触发器在给定特定交互(例如点击)的情况下提供事件信号是方便的。

你想要的是使用triggerMethod(https://github.com/marionettejs/backbone.marionette/blob/master/docs/marionette.functions.md#marionettetriggermethod)在布局中触发一个函数。见http://jsfiddle.net/ZxEa5/基本上,你想这在你的show功能:

childView.on("btn:clicked", function(){ 
    layout.triggerMethod("childView:btn:clicked"); 
}); 

而在你的布局:

onChildViewBtnClicked: function(){ 
    https://leanpub.com/marionette-gentle-introduction 
}); 

事件冒泡只负责收集自动地发生复合的观点,因为他们紧密地与他们的项目相关联?观点。如果你想要一个布局来监视它的一个子视图,你需要自己设置它。如果您想了解更多关于如何使用Marionette构建和清理代码的信息,可以查看我的书(https://leanpub.com/marionette-gentle-introduction),其中更详细地解释了这种类型的概念(及其应用)。

+1

在我的愚见中,如果一个布局会自动处理来自子节点的所有冒泡事件,它会更直观。否则,我会除了一个异常错误或至少一个事件根本没有处理的警告。这些都没有发生在最新的牵线木偶版本 –

1

我为类似问题实施了一个解决方案,如下所示。首先,我写了一个新的方法对入Marionette.View原型:

Marionette.View.prototype.bubbleMethod = function() { 
    var args = _.toArray(arguments) 
    var event = args.shift() 
    var bubble = event + ':bubble' 
    this.triggerMethod.apply(this, [ event ].concat(args)) 
    this.triggerMethod.apply(this, [ bubble ].concat(args)) 
} 

,将调用来自木偶常规triggerMethod两次:一次,因为它的目的是你的事件名称进行处理,而第二个这很容易被专门的观点识别,指定将事件向上冒泡。

然后你将需要这样的专业视图和冒泡的事件。你必须小心,不要像close(或所有的木偶事件)代表其他意见,因为这会导致区域和意见中的各种不可预知的行为。后缀:bubble可让您轻松识别泡泡的含义。冒泡观点可能是这样的:

var BubblingLayout = Marionette.Layout.extend({ 
    handleBubbles: function (view) { 
     var bubble = /:bubble$/ 
     this.listenTo(view, 'all', function() { 
      var args = _.toArray(arguments) 
      var event = args.shift() 
      if (event.match(bubble)) { 
       event = event.replace(bubble, '') 
       this.bubbleMethod.apply(this, [ event ].concat(args)) 
      } 
     }, this) 
    } 
}) 

你需要确保的最后一件事是能够起泡事件跨区域(布局和模块自定义区域经理)。这可以从一个区域的show事件调度处理,像这样:

var BubblingLayout = Marionette.Layout.extend({ 
    regions: { 
     sidebar: '#sidebar' 
    }, 
    initialize: function() { 
     this.sidebar.on('show', this.handleBubbles, this) 
    }, 
    handleBubbles: function (view) { 
     var bubble = /:bubble$/ 
     this.listenTo(view, 'all', function() { 
      var args = _.toArray(arguments) 
      var event = args.shift() 
      if (event.match(bubble)) { 
       event = event.replace(bubble, '') 
       this.bubbleMethod.apply(this, [ event ].concat(args)) 
      } 
     }, this) 
    } 
}) 

最后一部分是让一些真正的泡沫了,这是很容易被新bubbleMethod方法处理:

var MyView = Marionette.ItemView.extend({ 
    events: { 
     'click': 'clickHandler' 
    }, 
    clickHandler: function (ev) { 
     // do some stuff, then bubble something else 
     this.bubbleMethod('stuff:done') 
    } 
}) 

var BubblingLayout = Marionette.Layout.extend({ 
    regions: { 
     sidebar: '#sidebar' 
    }, 
    initialize: function() { 
     this.sidebar.on('show', this.handleBubbles, this) 
    }, 
    onRender: function() { 
     var view = new MyView() 
     this.sidebar.show(view) 
    }, 
    handleBubbles: function (view) { 
     var bubble = /:bubble$/ 
     this.listenTo(view, 'all', function() { 
      var args = _.toArray(arguments) 
      var event = args.shift() 
      if (event.match(bubble)) { 
       event = event.replace(bubble, '') 
       this.bubbleMethod.apply(this, [ event ].concat(args)) 
      } 
     }, this) 
    } 
}) 

现在您可以从代码中的任何地方处理冒泡事件,您可以在其中访问BubblingLayout的实例。

7

我不知道什么时候被引入这个木偶功能,但一个更简单的解决办法是使用childEvents哈希:http://marionettejs.com/docs/v2.4.1/marionette.layoutview.html#layoutview-childevents

... 
childEvents: { 
    "save:clicked" : "onSaveClicked" 
}, 
... 

你可以也直接孩子事件绑定到LayoutView之外的功能,如果它更有意义,就像这样:

layout.on('childview:save:clicked', function(childView) { 
    alert('clicked'); 
} 
+0

尝试过,并没有工作。它对你有用吗?我不得不明确地告诉布局“listenTo”它的孩子。例如:'this.listenTo(this.announcementRegion.currentView,“poisonpill”,()=> { this.announcementRegion.empty() });' –

+0

不,它适用于我很好,我试过这适用于CollectionView,LayoutView和CompositeView。 – kprist

+0

这是一个伟大的,最新的解决方案! – Seth