MarionetteJS:谁负责展示子应用程序?

时间:2016-01-11 10:14:10

标签: javascript backbone.js marionette

我正在构建一个非常简单的木偶应用程序;我没有使用Marionette.Module,因为它已被弃用,因为我想在Webpack中使用ES2015。

我只有几个“页面”:一个是欢迎屏幕,另一个是Playground。这些页面中的每一个都是Applications,另外还有一个带有Layout的根应用程序,只有三个区域:页眉,主页和页脚。

这些应用程序的视图(或布局)旨在填充根布局的main区域。

现在,每当我想展示其中一个子应用程序时,我都不知道如何(或者,我找不到最令人满意的方式)将根应用程序的布局问到showChildView这些子应用程序的视图/布局。

到目前为止,我想出了两种方法(其中没有一种方法很棒):

编辑:我在Q

结束时添加了另一种方法
  1. 在每个子应用程序的控制器上,触发视图中传递的“application:show”事件。根应用程序正在收到此事件,并在收到消息后立即showChildView
  2. 每当我启动一个子应用程序时,我都会将它传递给根应用程序实例。每当子应用程序需要显示自己时,它将调用showChildView区域内的main
  3. 第一种方法很弱,因为它完全是异步的(火与忘记)。我想知道我的应用程序何时显示(附加到DOM),但再次依赖另一个事件似乎很麻烦

    第二种方法更强大但很糟糕,因为我当然不希望子应用程序的视图在根布局中负责自己的渲染。根应用程序知道的更好。

    接下来是一些代码,试图展示这两个想法:

    // Approach #1
    
    // In the root app
    welcomeApp.on('app:show', (view) => {
       rootApp.rootView.showChildView('main', view);
    });
    
    // In the Welcome sub-app
    var Controller = {
        show() {
            app.trigger('app:show', new WelcomeView());
        }
    };
    
    // Approach #2
    
    // In the root application
    const welcomeApp = new WelcomeApp({
       rootApp: this
    });
    
    // In the Welcome sub-app
    var Controller = {
        show() {
            app.rootApp.rootLayout.showChildView('main', new WelcomeView());
        }
    };
    

    编辑:1月12日。

    好的,在文档中再挖一点我发现我认为这是正确的方法。这个想法是根应用程序将从子应用程序中侦听命令。

    所以,在我的根视图中,我会:

    this.channel.commands.setHandler("application:show", function(view) {
         this.rootView.showChildView('main', view);
    }.bind(this));
    

    在所有其他子应用程序中,我将(例如,在WelcomeView中):

    getController() {
    
        const greet = function () {
            this.channel.commands.execute('application:show', new WelcomeView());
        }.bind(this);
    
        return {
            greet: greet
        };
    }
    

1 个答案:

答案 0 :(得分:1)

就我个人而言,我不会使用多个应用程序,这似乎只是解决了被删除模块的问题。您是否尝试将单个应用程序与LayoutView,每个组件或(模块)的区域以及组件的基础作为单个JS对象一起使用,或者您可以尝试Backbone.Service将其拆分。如果您使用多条路线,可以查看Backbone.Routing,每条路线都是基地'控制器'对于'页面'。

我发现大规模木偶应用程序的精彩架构是James Kyle的Marionette Wires。这将Service用于可重用组件,以及不同数据类型的路由器/路由。

修改

构建使用服务的另一种方法,但如果您不希望根应用程序的区域显示从子组件调用的方法,则将实例化的应用程序导入子组件并使用app.addRegions方法在子项中添加区域。 EG

//app.js
import { Application } from 'backbone.marionette';

const App = Application.extend({
  onStart() {
    //doSomething();
  }...
});

export const app = new App();

//submodule/service.js
import { Service } from 'backbone.service';
import { SubmoduleController } from './controller';

const SubmoduleService = Service.extend({
  requests() {
    show: 'show',
    hide: 'hide'
  },

  setup(options = {}) {
    this.el = options.el
  },

  start() {
    this.controller = new SubmoduleController({
      el: this.el
    });
  },

  show() {
    this.controller.show();
  },

  hide() {
    this.controller.destroy();
  }
});

export const submoduleService = new SubmoduleService();

//submodule/controller.js
import { Object as Controller, Region } from 'backbone.marionette';
import { View } from './view';
import { app } from '../app';

export const SubmoduleController = Controller.extend({
  initialize(options = {}) {
    this.el = options.el;
    this._addRegions();
  },

  _addRegions() {
    const region = new Region({
      el: this.el
    });

    app.addRegions({
      submoduleRegion: region
    });
  },

  show() {
    const view = new View();
    app.submoduleRegion.show(view);
  },

  onDestroy() {
    app.submoduleRegion.reset();
  }
});

//main.js
import { submoduleService } from './submodule/service';

const config = {
  submodule: {
    el: '#submodule';
  },
  ...
};

submoduleService.setup(config.submodule);
submoduleService.show();
这样做的一个问题是子模块的区域需要它的元素在调用它的区域显示方法时存在于DOM中。这可以通过在应用程序上具有根视图,其模板包含所有组件根元素,或者具有根子模块 - 页面或其他内容来实现。