有没有办法从木偶.js中的显示控制器访问在列表控制器中创建的布局区域

Is there a way to access a layout's region that was created in a ListController from a ShowController in Marionette.js?

本文关键字:控制器 访问 列表 创建 区域 布局 显示 js 有没有      更新时间:2023-09-26

该应用程序有一个mainRegion,它显示动态布局。我有一个路由问题和访问布局并更新其pizzaTypeRegion的组合问题.此布局是在 list_controller.js.coffee 中创建的,它有一个pizzaTypeNameRegion(包含披萨类型名称)和一个pizzaTypeRegion(显示披萨类型详细信息)。我想在手动编辑网址时更新pizzaTypeRegionhttp://localhost:3000/#pizza_types .#pizza_types 按预期显示所有pizza_types。

我可以单击pizzaTypeNameRegion中的链接,它会使用正确的内容更新pizzaTypeRegion,没有任何问题。

在 url 中手动键入pizza_type id 时:

http://localhost:3000/#pizza_types/1 - 应显示第 1 种披萨类型,但不更新pizzaTypeRegion

http://localhost:3000/#pizza_types/2 - 应显示第二种披萨类型,但不更新pizzaTypeRegion

我正在获得证据,证明特定pizza_type是通过登录到控制台获得的。

pizza_types_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()

list_controller.js.咖啡

@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

show_controller.js.咖啡

@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)

如何使用新的披萨类型更新pizzaTypeRegion?有没有办法访问在list_controller中创建的布局实例,以便只使用新内容更新pizzaTypeRegion,而不会影响布局中的其他区域,通过手动键入 URL ?

**

编辑 **

  • 我摆脱了上面的代码并将所有内容放回原处,以便分离的关切可以维持。我最终没有使用全局,但是而是事件总线

list_controller:

newPizzaTypeRegion: (pizzaType) ->
  id = pizzaType.id
  App.vent.on "new:pizza:type:for:pizza:type:region", (pizzaTypeView) =>
    @layout.pizzaTypeRegion.show pizzaTypeView

show_controller:

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

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

很难给出一个好的答案,因为它取决于特定的实例。基本上您有 2 个选择:

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

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

在我的 pizza_types_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.咖啡

@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

list_controller.咖啡.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