代码之家  ›  专栏  ›  技术社区  ›  low_ghost

映射到嵌套组件的榆树效果

  •  2
  • low_ghost  · 技术社区  · 10 年前

    在这个 example (RandomGifPair) ,与NewGif对应的更新实际上是如何在父组件激发后执行的 RandomGif.update act model.left ? 看起来像是 RandomGif.update NewGif maybeUrl 需要在某处手动射击。更明确地说,RandomGifPair启动其Left更新操作,并通过手动调用RandomGif的更新函数来获取模型/效果对。返回的效果通过 Effects.map Left fx ,然后转到RandomGif中的getRandomGif函数

    getRandomGif : String -> Effects Action
    getRandomGif topic =
      Http.get decodeUrl (randomUrl topic)
        |> Task.toMaybe
        |> Task.map NewGif
        |> Effects.task
    

    据我所知,这将继续激发NewGif动作,由于效果的原因。地图,现在也被标记为“左”。我唯一遗漏的部分是如何将此操作保持在RandomGif的范围内,以及与此更新的NewGif情况相对应的操作实际触发:

    update : Action -> Model -> (Model, Effects Action)
    update action model =
      case action of
        RequestMore ->
          (model, getRandomGif model.topic)
    
        NewGif maybeUrl ->
          ( Model model.topic (Maybe.withDefault model.gifUrl maybeUrl)
          , Effects.none
          )
    

    当Main。elm仅具有RandomGifPair的更新功能,因此不支持NewGif。

    我确信答案在于端口的具体细节,Effects。map、forwardTo或我缺少的任务。

    作为参考, here is an attempt to solve the problem in javascript 它在NewGif的上部更新函数中包含一个条目,并手动调用RandomGif。更新内部。也许不是理解榆树的最好方法。。。

    2 回复  |  直到 10 年前
        1
  •  4
  •   Riley Lark    10 年前

    所有操作都进入顶级更新功能。没有办法将操作范围限定为子更新函数-它们总是位于顶部。因此,大多数程序将手动将操作向下路由到较低的更新函数。这就是这里发生的事情。所有动作都必须进入 RandomGifPair.update ,这取决于该函数a)调用子函数,b)将结果存储在状态的正确位置。它可能令人惊讶地繁琐。

    Here's the specific point in RandomGifPair.update that does the routing .

    第42行说“哦,这是一个 Left 行动给我 act 就在里面。现在你有了你想要的 NewGif RequestMore 存储在 行为 , 你知道它是去左边的。第44行调用较低的更新函数,该函数知道如何处理。第46行将较低更新函数的结果存储在模型中(通过用新的左侧重新创建整个模型并重新使用旧的右侧)。

    这一切都被Effects周围的样板所掩盖。如果你能先理解动作是如何流动的,然后再回去对效果应用同样的逻辑,我想这会变得更清楚。

        2
  •  0
  •   Mikeec3    10 年前

    我可能会迟到一点,但效果可以很容易地绘制出来。

    如下:

    type alias ChildModel = { number : Int }
    
    type alias Model = { firstChild : ChildModel }
    
    
    type ChildMsg = One | Two | Three
    
    type Msg Nothing | ChildMsg1 ChildMsg
    
    
    childUpdate : ChildMsg -> ChildModel -> (ChildModel, Cmd ChildMsg)
    childUpdate msg model =
      case msg of
        One -> { model | number = model.number + 1 }
        Two -> { model | number = model.number + 2 }
        Three -> { model | number = model.number + 3 }
    
    update : Msg -> Model -> (Model, Msg)
    update msg model =
      case msg of
        Nothing -> (model, Cmd.none)
        ChildMsg1 mesg -> -- heres where the update is mapped
          let
            (childModel, childMsg) = childUpdate mesg model.firstChild
          in
            ( { model | firstChild = childModel }, Cmd.map ChildMsg1 childMsg)
    

    命令。map将顶级消息映射到嵌套组件。想想蛇吃自己的尾巴。

    推荐文章