Elm 0.17:如何订阅兄弟/嵌套组件更改

afc*_*ano 2 architecture frontend elm

请参阅完整实施,并在此处提供已接受答案的建议:https://github.com/afcastano/elm-nested-component-communication

================================================== ===============

我有一个父组件有两个孩子.见工作示例

使用Elm Architecture,当左侧孩子的任何计数器发生变化时,如何更新正确的孩子?

目前,我让父组件读取左子模型的嵌套属性并将其设置为正确的子模型,但在我看来,父母不应该对子项的内部结构了解太多.

这些是模型和消息:

type alias MainModel =
  { counterPair : CounterPair
  , totals: Totals
  }

type alias CounterPair =
  {
    greenCounter : Counter
  , redCounter : Counter
  }

type alias Counter =
  {
    value : Int
  , totalClicks : Int  
  }

type alias Totals =
  {
    totalRed : Int
  , totalGreen : Int
  , combinedTotal : Int
  }

type MainMsg
  =  UpdateCounterPair CounterPairMsg
  |  UpdateTotals TotalsMsg


type alias RedVal = Int
type alias GreenVal = Int

type TotalsMsg
  = UpdateTotals RedVal GreenVal
Run Code Online (Sandbox Code Playgroud)

如您所见,Main模型包含两个子模型.该对模型依次包含两个计数器模型.

Total模型对Pair组件的CounterModel的更改感兴趣.

为此,主更新功能将如下所示:

updateMain: MainMsg -> MainModel -> MainModel
updateMain msg model =
  case msg of
    UpdateCounterPair counterPairMsg ->
    let 
      counterPairModel = updateCounterPair counterPairMsg model.counterPair
      totalsModel = updateTotals (UpdateTotals counterPair.redCounter.value counterPair.greenCounter.value) model.totals
    in
      {model | counterPair = counterPairModel, totals = totalsModel}
Run Code Online (Sandbox Code Playgroud)

我不喜欢的东西在这一行:

updateTotals (UpdateTotals counterPair.redCounter.value counterPair.greenCounter.value) model.totals
Run Code Online (Sandbox Code Playgroud)

1 - 主模块需要知道如何获取计数器的值,以便它可以将更新传递给updateTotal函数.

2 - Main模块还需要知道Totals模块的union类型的内部,以便它可以使用UpdateTotals构造函数.

有没有其他方式Totals组件可以订阅Pair组件而父级不知道模型结构的细节?

非常感谢你.

pda*_*moc 8

如果您有一个组件,并且您希望该组件具有副作用,换句话说,为了使其自身具有效果,您可以将一些信息(数据)与模型和Cmd一起返回:

update : Msg -> Model -> (Model, Cmd Msg, SomeInfo)

父母可以SomeInfo用来决定在其他地方做什么.

如果需要从外部更新组件,最好通过自定义更新功能公开它.在计数器的情况下,这将是这样的:

updateValue: Int -> Model -> Model

这样,您可以在模块中自由使用任何表示形式.然后,计数器的父级可以在遇到某些条件时更新计数器的模型.

类似的函数value : Model -> Int也可用于从计数器模型中提取信息.

所有这些都确保您在向模块用户呈现用于检索和更新数据的接口的同时保持封装.