如何显示和隐藏 Marionette.js 中的区域?

How can I show and hide regions in Marionette.js?

我正在尝试弄清楚如何在我的 Marionette.js 应用程序中使用路由器和控制器。我可以在我的应用程序的启动处理程序中启动初始页面,但我似乎无法弄清楚如何处理其他路由。这个 SPA 并不复杂,我的用户只有三个页面。一个是线索 table 视图、车辆 table 视图和单个车辆的视图。在弄清楚此路线的工作原理之前,我并不担心单一车辆视图。

// my app
var App = new Marionette.Application({});

// my lead and vehicle model rows
App.vehicleRowView = Marionette.ItemView.extend({
  tagName: 'tr',
  template: '#vehicle-row-tpl'
});
App.leadRowView = Marionette.ItemView.extend({
  tagName: 'tr',
  template: '#lead-row-tpl'
});

// composite views for the tables
App.vehicleTableView = Marionette.CompositeView.extend({
  tagName: 'div',
  className: 'row',
  template: '#vehicles-table',
  childViewContainer: 'tbody',
  childView: App.vehicleRowView
});
App.leadsTableView = Marionette.CompositeView.extend({
  tagName: 'div',
  className: 'row',
  template: '#leads-table',
  childViewContainer: 'tbody',
  childView: App.leadRowView
});

// controller
var Controller = Marionette.Object.extend({
  leads: function() {
    var leadstable = new App.leadsTableView({
      collection: this.leads
    });
    App.regions.leads.show(leadstable);
  },
  vehicles: function() {
    console.log('vehicles...');
  }
});

// router
var AppRouter = Marionette.AppRouter.extend({
  controller: new Controller,
  appRoutes: {
    'leads': 'leads',
    'vehicles': 'vehicles'
  }
});
App.router = new AppRouter;
App.vehicles = [];
App.leads = [];


// Start handlers
App.on('before:start', function() {
  this.vehicles = new Vehicles();
  this.vehicles.fetch();
  this.leads = new Leads();
  this.leads.fetch();

  var appContainerLayoutView = Marionette.LayoutView.extend({
    el: '#app-container',
    regions: {
      vehicles: '#vehicles-content',
      leads: '#leads-content'
    }
  });
  this.regions = new appContainerLayoutView();
});

App.on('start', function() {
  Backbone.history.start({pushState: true});
  var vehiclesLayoutView = new this.vehicleTableView({
    collection: this.vehicles
  });
  App.regions.vehicles.show(vehiclesLayoutView);
});

App.start();

启动时,首页正常。但是,当我转到#leads 时,我的线索 table 没有呈现。实际上,路线并没有发生,并且 URL 更改为 /#leads。如果我然后转到 URL,table 骨架呈现,但不呈现数据。集合在 before:start 上加载正常,模板也正常。我必须去 URL 两次,但是 table 没有数据,即使我的 App.leads 集合加载正常。不过,我的 console.log 输出确认我正在到达路线。

我想在用户前往#leads 路线时隐藏车辆区域。当用户转到#vehicles 时,我想隐藏我的线索 table 并显示车辆(与我的启动处理程序相同的视图)。

我觉得我就在那里,但缺少一些基本的东西。

通过查看您的 vehiclesleads 区域,我怀疑您误解了区域的作用。如果您希望它们相互交换,那么您将只创建一个区域并在您想要展示车辆时使用该区域 .show( new VehiclesView() );,在您希望线索替换车辆时使用该区域 .show( new LeadsView() );

这是一个工作示例:

var app = new Mn.Application();

var Controller = Mn.Object.extend({
  leads: function(){
    app.regions.setActive('leads').getRegion('main').show( new LeadsView() );
  },
  vehicles: function(){
    app.regions.setActive('vehicles').getRegion('main').show( new VehiclesView() );
  }
});

var VehiclesView = Mn.ItemView.extend({
  template: _.template('،°. ˘Ô≈ôﺣ » » »')
});
var LeadsView = Mn.ItemView.extend({
  template: _.template("( /.__.)/ (.__.)")
});

var AppLayoutView = Mn.LayoutView.extend({
  el: '#app',
  regions: { main: 'main' },
  events: { 'click nav a': 'onClick' },
  onClick: function(evt){
    evt.preventDefault();
    var viewName = evt.currentTarget.dataset.view;
    app.controller[viewName]();
    app.router.navigate(viewName);
  },
  setActive: function(viewName){
    /** it might seem that it is easier to just 
    make the link bold on click, but you would have 
    to handle it if you want to make it active on page load */
    this.$('nav a').
      removeClass('active').
      filter('[data-view="'+viewName+'"]').
      addClass('active');
    return this;
  }
});

app.on('start',function(){
  
  app.regions = new AppLayoutView();
  
  app.controller = new Controller();
  app.router = new Mn.AppRouter({
    controller: app.controller
  });
  Backbone.history.start({pushState: true});
  
  /** show initial content */
  app.controller.leads();
  app.router.navigate('leads');
  
});

app.start();
.active { font-weight :bold ;}
<script src='http://code.jquery.com/jquery.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.2.3/backbone.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/backbone.marionette/2.4.3/backbone.marionette.js'></script>
  
<div id="app">
  <nav>
    <a href="#" data-view="vehicles">Vehicles</a>
    <a href="#" data-view="leads">Leads</a>
  </nav>
  <main></main>
</div>