Javascript 是否有方法访问布局';从Marionette.js中的ShowController在ListController中创建的区域?

Javascript 是否有方法访问布局';从Marionette.js中的ShowController在ListController中创建的区域?,javascript,coffeescript,marionette,Javascript,Coffeescript,Marionette,该应用程序有一个mainRegion,显示动态布局。我遇到了一个组合问题,即路由问题和访问布局,以及更新其pizzaTypeRegion。此布局是在list_controller.js.coffee中创建的,它有一个pizzaTypeNameRegion(保存pizza类型名称)和一个pizzaTypeRegion(显示pizza类型的详细信息)。我想在手动编辑url时更新pizzaTypeRegion:http://localhost:3000/#pizza_types#pizza_类型按预期

该应用程序有一个mainRegion,显示动态布局。我遇到了一个组合问题,即路由问题和访问布局,以及更新其
pizzaTypeRegion
。此布局是在list_controller.js.coffee中创建的,它有一个
pizzaTypeNameRegion
(保存pizza类型名称)和一个
pizzaTypeRegion
(显示pizza类型的详细信息)。我想在手动编辑url时更新
pizzaTypeRegion
http://localhost:3000/#pizza_types
#pizza_类型按预期显示所有pizza_类型

我可以点击
pizzaTypeNameRegion
中的链接,它会用正确的内容更新
pizzaTypeRegion
,而不会出现任何问题

在url中手动键入比萨饼的id时:

@Pizzeria.module "PizzaTypesApp", (PizzaTypesApp, App, Backbone, Marionette,$, _) ->
  @startWithParent = false

  # took this out of the list_view    
  class PizzaTypeName extends Backbone.Marionette.ItemView
    template: "pizza_types/list/templates/_pizza_type_name"
    modelEvents:
      "change" : "render"

    events:
      "click a" : "showPizzaType"

    showPizzaType: (event) ->
      @trigger "show:pizza:type", @model
      @model     

  class PizzaTypeNames extends Backbone.Marionette.CompositeView
    template: "pizza_types/list/templates/pizza_type_names"
    itemView: PizzaTypeName

  # took this out of the list_view 
  class DefaultLayout extends Backbone.Marionette.Layout
    template: "pizza_types/list/templates/pizza_types_layout"
    regions:
      pizzaTypeNameRegion : "#pizza-type-name-region"
      pizzaTypeRegion : "#pizza-type-region"

  App.addInitializer ->
    @layout = new DefaultLayout
    Pizzeria.PizzaTypesApp.layout = @layout
    App.mainRegion.show @layout

    @layout.on "show", =>
      pizzaTypes = App.request "get:pizza:types:entities"   
      pizzaTypesNameView = new PizzaTypeNames
        collection: pizzaTypes

      @layout.pizzaTypeNameRegion.show pizzaTypesNameView 
      @layout.pizzaTypeRegion

  class PizzaTypesApp.Router extends Marionette.AppRouter
    appRoutes:
      "pizza_types" : "listPizzaTypes"
      "pizza_types/:id" : "showPizzaType"


  API =

   listPizzaTypes: ->
     PizzaTypesApp.List.Controller.listPizzaTypes()

   showPizzaType: (id) ->   
     PizzaTypesApp.Show.Controller.showPizzaTypeFromEvent id

   showFirstPizzaType: ->
     PizzaTypesApp.Show.Controller.showFirstPizzaType()

  App.on "pizzaTypes:show", ->
    App.navigate "pizza_types"
    API.listPizzaTypes()

  App.addInitializer ->
    new PizzaTypesApp.Router
      controller: API

  App.reqres.setHandler "show:pizza:type:view", (model) ->
    API.showPizzaType model

  App.reqres.setHandler "show:first:pizzaType:view", ->
    API.showFirstPizzaType()
http://localhost:3000/#pizza_types/1
-应显示第一种比萨饼类型,但不更新
比萨饼类型区域

http://localhost:3000/#pizza_types/2
-应显示第二种比萨饼类型,但不更新
比萨饼类型区域

我得到的证据表明,特定的pizza_类型是通过登录控制台获得的

比萨\u类型\u app.js.咖啡

@Pizzeria.module "PizzaTypesApp", (PizzaTypesApp, App, Backbone, Marionette,$, _) ->
  @startWithParent = false

  class PizzaTypesApp.Router extends Marionette.AppRouter
    appRoutes:
      "pizza_types" : "listPizzaTypes"
      "pizza_types/:id" : "showPizzaType"

  API =

   listPizzaTypes: ->
     PizzaTypesApp.List.Controller.listPizzaTypes()

   showPizzaType: (model) ->   
     PizzaTypesApp.Show.Controller.showPizzaTypeFromEvent model     


  App.on "pizzaTypes:show", ->
    App.navigate "pizza_types"
    API.listPizzaTypes()

  App.addInitializer ->
    new PizzaTypesApp.Router
      controller: API

  App.reqres.setHandler "show:pizza:type:view", (model) ->
    API.showPizzaType model

  App.reqres.setHandler "show:first:pizzaType:view", ->
    API.showFirstPizzaType()
@Pizzeria.module "PizzaTypesApp.List", (List, App, Backbone, Marionette, $, _) ->

      List.Controller =

        listPizzaTypes: ->
          pizzaTypes = App.request "get:pizza:types:entities"
          pizzaType = gon.pizza_type
          @layout = new List.Layout

          @layout.on "show", =>
            @pizzaTypeNameRegion pizzaTypes
            @pizzaTypeRegion()

          App.mainRegion.show @layout

        pizzaTypeNameRegion: (pizzaTypes) ->
          pizzaTypesNameView = new List.PizzaTypeNames
            collection: pizzaTypes
          @layout.pizzaTypeNameRegion.show pizzaTypesNameView

          pizzaTypesNameView.on "itemview:show:pizza:type", (childView, pizzaType) =>
            @newPizzaTypeRegion(pizzaType)

        pizzaTypeRegion: ->
          initialPizzaTypeView = App.request "show:first:pizzaType:view"
          @layout.pizzaTypeRegion.show initialPizzaTypeView

        newPizzaTypeRegion: (pizzaType) ->
          newPizzaTypeView = App.request "show:pizza:type:view", pizzaType.id
          @layout.pizzaTypeRegion.show newPizzaTypeView
@Pizzeria.module "PizzaTypesApp.Show", (Show, App, Backbone, Marionette, $, _) ->

  Show.Controller =

    showPizzaTypeFromEvent: (model) ->
      pizzaType = App.request "pizzaType:entity", model
      pizzaTypeView = new Show.PizzaType
        model: pizzaType
      App.mainRegion.show pizzaTypeView  
      # mainRegion is updated with whatever the url is 
      # ex)`http://localhost:3000/#pizza_types/2` will 
      # place the pizza_type with the id of 2 in the 
      # App's mainRegion, breaking the layout that I 
      # set up in the list_controller.js.coffee. Browser back and forward
      # buttons work, but layout is broken, missing other regions (and their info)
@Pizzeria.module "PizzaTypesApp.Show", (Show, App, Backbone, Marionette, $, _) ->

  Show.Controller =

    showPizzaTypeFromEvent: (id) ->
      pizzaType = App.request "pizzaType:entity", id
      pizzaTypeView = new Show.PizzaType
        model: pizzaType
      pizzaTypeView

      @layout = Pizzeria.PizzaTypesApp.layout
      App.mainRegion.show @layout
      @layout.pizzaTypeRegion.show pizzaTypeView
列出\u controller.js.coffee

@Pizzeria.module "PizzaTypesApp", (PizzaTypesApp, App, Backbone, Marionette,$, _) ->
  @startWithParent = false

  class PizzaTypesApp.Router extends Marionette.AppRouter
    appRoutes:
      "pizza_types" : "listPizzaTypes"
      "pizza_types/:id" : "showPizzaType"

  API =

   listPizzaTypes: ->
     PizzaTypesApp.List.Controller.listPizzaTypes()

   showPizzaType: (model) ->   
     PizzaTypesApp.Show.Controller.showPizzaTypeFromEvent model     


  App.on "pizzaTypes:show", ->
    App.navigate "pizza_types"
    API.listPizzaTypes()

  App.addInitializer ->
    new PizzaTypesApp.Router
      controller: API

  App.reqres.setHandler "show:pizza:type:view", (model) ->
    API.showPizzaType model

  App.reqres.setHandler "show:first:pizzaType:view", ->
    API.showFirstPizzaType()
@Pizzeria.module "PizzaTypesApp.List", (List, App, Backbone, Marionette, $, _) ->

      List.Controller =

        listPizzaTypes: ->
          pizzaTypes = App.request "get:pizza:types:entities"
          pizzaType = gon.pizza_type
          @layout = new List.Layout

          @layout.on "show", =>
            @pizzaTypeNameRegion pizzaTypes
            @pizzaTypeRegion()

          App.mainRegion.show @layout

        pizzaTypeNameRegion: (pizzaTypes) ->
          pizzaTypesNameView = new List.PizzaTypeNames
            collection: pizzaTypes
          @layout.pizzaTypeNameRegion.show pizzaTypesNameView

          pizzaTypesNameView.on "itemview:show:pizza:type", (childView, pizzaType) =>
            @newPizzaTypeRegion(pizzaType)

        pizzaTypeRegion: ->
          initialPizzaTypeView = App.request "show:first:pizzaType:view"
          @layout.pizzaTypeRegion.show initialPizzaTypeView

        newPizzaTypeRegion: (pizzaType) ->
          newPizzaTypeView = App.request "show:pizza:type:view", pizzaType.id
          @layout.pizzaTypeRegion.show newPizzaTypeView
@Pizzeria.module "PizzaTypesApp.Show", (Show, App, Backbone, Marionette, $, _) ->

  Show.Controller =

    showPizzaTypeFromEvent: (model) ->
      pizzaType = App.request "pizzaType:entity", model
      pizzaTypeView = new Show.PizzaType
        model: pizzaType
      App.mainRegion.show pizzaTypeView  
      # mainRegion is updated with whatever the url is 
      # ex)`http://localhost:3000/#pizza_types/2` will 
      # place the pizza_type with the id of 2 in the 
      # App's mainRegion, breaking the layout that I 
      # set up in the list_controller.js.coffee. Browser back and forward
      # buttons work, but layout is broken, missing other regions (and their info)
@Pizzeria.module "PizzaTypesApp.Show", (Show, App, Backbone, Marionette, $, _) ->

  Show.Controller =

    showPizzaTypeFromEvent: (id) ->
      pizzaType = App.request "pizzaType:entity", id
      pizzaTypeView = new Show.PizzaType
        model: pizzaType
      pizzaTypeView

      @layout = Pizzeria.PizzaTypesApp.layout
      App.mainRegion.show @layout
      @layout.pizzaTypeRegion.show pizzaTypeView
show_controller.js.coffee

@Pizzeria.module "PizzaTypesApp", (PizzaTypesApp, App, Backbone, Marionette,$, _) ->
  @startWithParent = false

  class PizzaTypesApp.Router extends Marionette.AppRouter
    appRoutes:
      "pizza_types" : "listPizzaTypes"
      "pizza_types/:id" : "showPizzaType"

  API =

   listPizzaTypes: ->
     PizzaTypesApp.List.Controller.listPizzaTypes()

   showPizzaType: (model) ->   
     PizzaTypesApp.Show.Controller.showPizzaTypeFromEvent model     


  App.on "pizzaTypes:show", ->
    App.navigate "pizza_types"
    API.listPizzaTypes()

  App.addInitializer ->
    new PizzaTypesApp.Router
      controller: API

  App.reqres.setHandler "show:pizza:type:view", (model) ->
    API.showPizzaType model

  App.reqres.setHandler "show:first:pizzaType:view", ->
    API.showFirstPizzaType()
@Pizzeria.module "PizzaTypesApp.List", (List, App, Backbone, Marionette, $, _) ->

      List.Controller =

        listPizzaTypes: ->
          pizzaTypes = App.request "get:pizza:types:entities"
          pizzaType = gon.pizza_type
          @layout = new List.Layout

          @layout.on "show", =>
            @pizzaTypeNameRegion pizzaTypes
            @pizzaTypeRegion()

          App.mainRegion.show @layout

        pizzaTypeNameRegion: (pizzaTypes) ->
          pizzaTypesNameView = new List.PizzaTypeNames
            collection: pizzaTypes
          @layout.pizzaTypeNameRegion.show pizzaTypesNameView

          pizzaTypesNameView.on "itemview:show:pizza:type", (childView, pizzaType) =>
            @newPizzaTypeRegion(pizzaType)

        pizzaTypeRegion: ->
          initialPizzaTypeView = App.request "show:first:pizzaType:view"
          @layout.pizzaTypeRegion.show initialPizzaTypeView

        newPizzaTypeRegion: (pizzaType) ->
          newPizzaTypeView = App.request "show:pizza:type:view", pizzaType.id
          @layout.pizzaTypeRegion.show newPizzaTypeView
@Pizzeria.module "PizzaTypesApp.Show", (Show, App, Backbone, Marionette, $, _) ->

  Show.Controller =

    showPizzaTypeFromEvent: (model) ->
      pizzaType = App.request "pizzaType:entity", model
      pizzaTypeView = new Show.PizzaType
        model: pizzaType
      App.mainRegion.show pizzaTypeView  
      # mainRegion is updated with whatever the url is 
      # ex)`http://localhost:3000/#pizza_types/2` will 
      # place the pizza_type with the id of 2 in the 
      # App's mainRegion, breaking the layout that I 
      # set up in the list_controller.js.coffee. Browser back and forward
      # buttons work, but layout is broken, missing other regions (and their info)
@Pizzeria.module "PizzaTypesApp.Show", (Show, App, Backbone, Marionette, $, _) ->

  Show.Controller =

    showPizzaTypeFromEvent: (id) ->
      pizzaType = App.request "pizzaType:entity", id
      pizzaTypeView = new Show.PizzaType
        model: pizzaType
      pizzaTypeView

      @layout = Pizzeria.PizzaTypesApp.layout
      App.mainRegion.show @layout
      @layout.pizzaTypeRegion.show pizzaTypeView
如何用新的比萨饼类型更新
pizzatyperence
?是否有方法访问在list_controller中创建的布局实例,以便仅使用新内容更新
pizzaTypeRegion
,而不通过手动键入URL影响布局中的其他区域

**编辑**


  • 我去掉了上面的代码,把所有的东西都放回原处 可以保持对各种问题的关注。我最终没有使用一个全局的,但是 而不是事件总线
:

列出您的控制器:

newPizzaTypeRegion: (pizzaType) ->
  id = pizzaType.id
  App.vent.on "new:pizza:type:for:pizza:type:region", (pizzaTypeView) =>
    @layout.pizzaTypeRegion.show pizzaTypeView
showPizzaTypeFromEvent: (id) ->
  pizzaType = App.request "pizzaType:entity", id
  pizzaTypeView = new Show.PizzaType
    model: pizzaType
  App.vent.trigger "new:pizza:type:for:pizza:type:region", pizzaTypeView
显示控制器:

newPizzaTypeRegion: (pizzaType) ->
  id = pizzaType.id
  App.vent.on "new:pizza:type:for:pizza:type:region", (pizzaTypeView) =>
    @layout.pizzaTypeRegion.show pizzaTypeView
showPizzaTypeFromEvent: (id) ->
  pizzaType = App.request "pizzaType:entity", id
  pizzaTypeView = new Show.PizzaType
    model: pizzaType
  App.vent.trigger "new:pizza:type:for:pizza:type:region", pizzaTypeView

Controller知道如何更新自己,Show.Controller告诉List.Controller要更新的内容。效果很好,非常干净,而且是解耦的。

很难给出一个好的答案,因为它取决于具体的实例。基本上你有两个选择:

  • 将布局附加到可访问的位置(不一定是全局布局,它可以位于子应用程序级别)
  • 使用事件对修改作出反应并更新布局/视图

如果在多个视图中使用此布局,另一件要调查的事情是在子应用程序的初始值设定项中实例化它,并将其附加到某个位置(例如子应用程序),以便可以从多个控制器访问它。

在我的pizza\u types\u app.js.coffee子模块中:

@Pizzeria.module "PizzaTypesApp", (PizzaTypesApp, App, Backbone, Marionette,$, _) ->
  @startWithParent = false

  # took this out of the list_view    
  class PizzaTypeName extends Backbone.Marionette.ItemView
    template: "pizza_types/list/templates/_pizza_type_name"
    modelEvents:
      "change" : "render"

    events:
      "click a" : "showPizzaType"

    showPizzaType: (event) ->
      @trigger "show:pizza:type", @model
      @model     

  class PizzaTypeNames extends Backbone.Marionette.CompositeView
    template: "pizza_types/list/templates/pizza_type_names"
    itemView: PizzaTypeName

  # took this out of the list_view 
  class DefaultLayout extends Backbone.Marionette.Layout
    template: "pizza_types/list/templates/pizza_types_layout"
    regions:
      pizzaTypeNameRegion : "#pizza-type-name-region"
      pizzaTypeRegion : "#pizza-type-region"

  App.addInitializer ->
    @layout = new DefaultLayout
    Pizzeria.PizzaTypesApp.layout = @layout
    App.mainRegion.show @layout

    @layout.on "show", =>
      pizzaTypes = App.request "get:pizza:types:entities"   
      pizzaTypesNameView = new PizzaTypeNames
        collection: pizzaTypes

      @layout.pizzaTypeNameRegion.show pizzaTypesNameView 
      @layout.pizzaTypeRegion

  class PizzaTypesApp.Router extends Marionette.AppRouter
    appRoutes:
      "pizza_types" : "listPizzaTypes"
      "pizza_types/:id" : "showPizzaType"


  API =

   listPizzaTypes: ->
     PizzaTypesApp.List.Controller.listPizzaTypes()

   showPizzaType: (id) ->   
     PizzaTypesApp.Show.Controller.showPizzaTypeFromEvent id

   showFirstPizzaType: ->
     PizzaTypesApp.Show.Controller.showFirstPizzaType()

  App.on "pizzaTypes:show", ->
    App.navigate "pizza_types"
    API.listPizzaTypes()

  App.addInitializer ->
    new PizzaTypesApp.Router
      controller: API

  App.reqres.setHandler "show:pizza:type:view", (model) ->
    API.showPizzaType model

  App.reqres.setHandler "show:first:pizzaType:view", ->
    API.showFirstPizzaType()
show_controller.js.coffee

@Pizzeria.module "PizzaTypesApp", (PizzaTypesApp, App, Backbone, Marionette,$, _) ->
  @startWithParent = false

  class PizzaTypesApp.Router extends Marionette.AppRouter
    appRoutes:
      "pizza_types" : "listPizzaTypes"
      "pizza_types/:id" : "showPizzaType"

  API =

   listPizzaTypes: ->
     PizzaTypesApp.List.Controller.listPizzaTypes()

   showPizzaType: (model) ->   
     PizzaTypesApp.Show.Controller.showPizzaTypeFromEvent model     


  App.on "pizzaTypes:show", ->
    App.navigate "pizza_types"
    API.listPizzaTypes()

  App.addInitializer ->
    new PizzaTypesApp.Router
      controller: API

  App.reqres.setHandler "show:pizza:type:view", (model) ->
    API.showPizzaType model

  App.reqres.setHandler "show:first:pizzaType:view", ->
    API.showFirstPizzaType()
@Pizzeria.module "PizzaTypesApp.List", (List, App, Backbone, Marionette, $, _) ->

      List.Controller =

        listPizzaTypes: ->
          pizzaTypes = App.request "get:pizza:types:entities"
          pizzaType = gon.pizza_type
          @layout = new List.Layout

          @layout.on "show", =>
            @pizzaTypeNameRegion pizzaTypes
            @pizzaTypeRegion()

          App.mainRegion.show @layout

        pizzaTypeNameRegion: (pizzaTypes) ->
          pizzaTypesNameView = new List.PizzaTypeNames
            collection: pizzaTypes
          @layout.pizzaTypeNameRegion.show pizzaTypesNameView

          pizzaTypesNameView.on "itemview:show:pizza:type", (childView, pizzaType) =>
            @newPizzaTypeRegion(pizzaType)

        pizzaTypeRegion: ->
          initialPizzaTypeView = App.request "show:first:pizzaType:view"
          @layout.pizzaTypeRegion.show initialPizzaTypeView

        newPizzaTypeRegion: (pizzaType) ->
          newPizzaTypeView = App.request "show:pizza:type:view", pizzaType.id
          @layout.pizzaTypeRegion.show newPizzaTypeView
@Pizzeria.module "PizzaTypesApp.Show", (Show, App, Backbone, Marionette, $, _) ->

  Show.Controller =

    showPizzaTypeFromEvent: (model) ->
      pizzaType = App.request "pizzaType:entity", model
      pizzaTypeView = new Show.PizzaType
        model: pizzaType
      App.mainRegion.show pizzaTypeView  
      # mainRegion is updated with whatever the url is 
      # ex)`http://localhost:3000/#pizza_types/2` will 
      # place the pizza_type with the id of 2 in the 
      # App's mainRegion, breaking the layout that I 
      # set up in the list_controller.js.coffee. Browser back and forward
      # buttons work, but layout is broken, missing other regions (and their info)
@Pizzeria.module "PizzaTypesApp.Show", (Show, App, Backbone, Marionette, $, _) ->

  Show.Controller =

    showPizzaTypeFromEvent: (id) ->
      pizzaType = App.request "pizzaType:entity", id
      pizzaTypeView = new Show.PizzaType
        model: pizzaType
      pizzaTypeView

      @layout = Pizzeria.PizzaTypesApp.layout
      App.mainRegion.show @layout
      @layout.pizzaTypeRegion.show pizzaTypeView
列出\u controller.coffee.js

@Pizzeria.module "PizzaTypesApp.List", (List, App, Backbone, Marionette, $, _) ->

  List.Controller =

    listPizzaTypes: ->
      pizzaTypes = App.request "get:pizza:types:entities"
      pizzaType = gon.pizza_type
      @layout = Pizzeria.PizzaTypesApp.layout #new List.Layout

      @layout.on "show", =>
        @pizzaTypeRegion()

      App.mainRegion.show @layout

    pizzaTypeNameRegion: (pizzaTypes) ->
      pizzaTypesNameView = new List.PizzaTypeNames
        collection: pizzaTypes
      @layout.pizzaTypeNameRegion.show pizzaTypesNameView

      pizzaTypesNameView.on "itemview:show:pizza:type", (childView, pizzaType) =>
        @newPizzaTypeRegion(pizzaType)

    pizzaTypeRegion: ->
      initialPizzaTypeView = App.request "show:first:pizzaType:view"
      @layout.pizzaTypeRegion.show initialPizzaTypeView

    newPizzaTypeRegion: (pizzaType) ->
      newPizzaTypeView = App.request "show:pizza:type:view", pizzaType.id
      @layout.pizzaTypeRegion.show newPizzaTypeView


    getPizzaTypeNameView: (pizzaTypes) ->
      new List.PizzaTypeNames
        collection: pizzaTypes

    getPizzaTypeLayout: ->
      new List.Layout

我需要找到一种将布局附加到全局对象的方法,或者在route事件中传递布局。有什么好办法可以继续吗?再次感谢你的回答,我希望有一天能报答你。我把代码贴在下面。它可以工作,但我不确定这是否是一个反模式,因为缺乏JS方面的经验(用它编写代码只有7个月左右)。关于这个解决方案有什么一般性的建议吗?这似乎模糊了关注点之间的分离,但还有其他选择吗?我不知道,因为JS的范围。在应用程序中放在更高级别是有意义的,这样可以被引用。使用事件会允许在不移动视图代码的情况下访问特定布局实例的区域吗?我去掉了上面的代码并将所有内容放回原处,这样可以保持关注点的分离。我最终没有使用全局总线,而是使用事件总线。