9

我有一个带有区域的布局视图,在该区域中我有一个触发事件的项目视图,但它似乎没有冒泡到布局视图。我做错了什么还是这是设计的行为?我假设没有添加 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"
        }
    });

更新:

看到这个小提琴http://jsfiddle.net/7ATMz/11/我设法让布局视图监听子事件,但我必须将它连接到布局视图本身之外并打破封装。无论如何,我可以在布局视图中执行此操作吗?

谢谢,

乔恩

4

5 回答 5

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

事件冒泡只会在 collection?composite 视图中自动发生,因为它们与其项目视图紧密相关。如果您希望布局监控其子视图之一,则需要自行设置。

无耻插件:如果您想了解更多关于如何使用 Marionette 构建和清理代码,您可以查看我的书 ( https://leanpub.com/marionette-gentle-introduction ),其中包含此类概念(及其应用程序)更详细地解释。

于 2013-06-01T12:37:28.440 回答
7

我不确定何时引入了这个 Marionette 功能,但更简单的解决方案是使用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');
}
于 2015-05-15T12:14:17.713 回答
4

我建议使用 Backbone.Courier 来满足这种需求:https ://github.com/rotundasoftware/backbone.courier

于 2013-10-07T15:44:22.467 回答
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))
}

这将调用triggerMethodMarionette 的常规两次:一次使用您的事件名称,因为它打算被处理,第二次使用专门的视图很容易识别,指定用于冒泡事件。

然后,您将需要此类专门的视图和冒泡事件,这些事件旨在被冒泡。您必须注意不要close代表其他视图调度事件(或任何 Marionette 事件),因为这将导致区域和视图中的各种不可预测的行为。后缀使您可以轻松识别冒泡的: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.

于 2013-10-07T15:33:12.813 回答
0

为什么不让点击事件冒泡 DOM 层次结构并在您的布局视图中处理它?像这样的东西(在这里小提琴):

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"   
    }*/
});
于 2013-05-31T23:10:14.297 回答