0

我有一个复杂的 Backbone/Marionette 应用程序,我经常将事情发泄给父元素。但是,当我需要从父元素触发子元素时,我有点不清楚我应该如何做到这一点。最简单的方法就是从父级调用子级的方法,但是,我想知道在这种情况下我是否在“作弊”(并且可能导致内存泄漏问题或其他问题?)我很好奇“正确的路。

这是我的代码的一个极其简化的人为版本的 jsfiddle。以及基于需求的应用程序中相同设计示例的要点

<header>
    <h4>A subview/view trigger event loop playground</h4>
    <p>Open your console and then click the button</p>
</header>

<article id="main">
</article>

<script type="text/html" id="MySubView">
    <button type="button" id="button">Click Me</button>
</script>

<script type="text/html" id="MyView">
    <div id="myRegion"></div>
</script>


<script>
var app = new Marionette.Application();

app.addRegions({
    "mainRegion": "#main" 
});

app.module("SampleModule", function(Mod, App, Backbone, Marionette, $, _){

    var MySubView = Marionette.ItemView.extend({
        template: '#MySubView',
        events: {
            'click #button': 'sendClick'
        },

        triggers: {
            'afterClick': 'afterClick'
        },

        initialize: function initialize(){
            this.on('afterClick', this.afterClick);
        },

        sendClick: function(e) {
            e.preventDefault();
            console.log('Good... Use your ventful capabilities boy...');
            //trigger some method in the parent...
            this.trigger('processClick');
        },

        afterClick: function(who) {
            console.log("I've been waiting for you... The circle is now complete. When I left you I was the but the sender, now I am the receiver...", who);
        }
    });

    var MyView = Marionette.Layout.extend({
        template: '#MyView',
        views: {},
        regions: {
            myRegion: '#myRegion'
        },

        onShow: function onShow(){
            this.views.mySubView = new MySubView({ model: this.model }).on('processClick', this.sendBackClick, this);
            this.myRegion.show(this.views.mySubView);
        },

        sendBackClick: function(){
            //do some stuff, then, let the child know you're done...
            console.log('heh heh heh heh.... Goood, goooood! Your triggers have made you powerful. Now, fulfil your parents destiny and take the event at my side!!!');
            //use trigger?
            this.views.mySubView.trigger('afterClick', 'from trigger');
            //call method directly?
            this.views.mySubView.afterClick('called directly');
        }
    });


    var Controller = Marionette.Controller.extend({

        initialize: function(options){
            this.region = options.region
        },

        show: function(){
            var mainView = new MyView({ model: new Backbone.Model({'prop':'value'}) });

            this.region.show(mainView);
        }
    });


    Mod.addInitializer(function(){
        Mod.controller = new Controller({
            region: app.mainRegion
        });
        Mod.controller.show();
    });
});

app.start();
</script>

顺便说一句:注意我在父级上使用“视图”属性来跟踪它的子级。如果有更好的方法可以做到这一点,或者为什么这是错误的原因,我很想听听。

4

1 回答 1

2

几件事可能会或可能不会回答您的问题:

首先,在您设计的示例中,很明显您希望孩子知道“点击”已由父母处理,但在现实世界中,我猜这实际上可能不是相关的信息。也许孩子应该完全听别的东西?例如,您的布局和您的子视图碰巧共享一个模型。我将迈出一大步,猜测点击事件实际上是为了启动该模型的一些处理。如果是这种情况,孩子真正想知道的可能是模型上触发的事件(内置或自定义)。通过这种方式,子视图可以适当地响应事件,即使它最初不是来自点击(在我看来,有一天可能会有多条路径是合理的)。的确,这是做了很多假设。如果它不是这个事件的中心的模型,它仍然可能是子视图以外的东西——app.vent?父布局本身?一切都取决于确切的用例。

其次,在定义布局时注意创建视图对象。这将是您实例化的布局的各个实例之间的共享引用。这可能是你想要的,但是(再次假设)我猜不是。

于 2013-08-19T17:48:47.320 回答