映射到嵌套组件的 Elm 效果
Elm Effects Mapped to Nested Component
在这个example (RandomGifPair)中,NewGif对应的update实际上是如何连接到父组件触发后执行的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 动作,由于 Effects.map,它现在也被标记为 Left。图片中我唯一缺少的部分是这个动作是如何保持在 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.update。可能不是尝试理解榆树的最佳方式...
所有操作都会进入您的 top-level 更新功能。无法将操作范围限定为 sub-update 函数 - 它们总是位于顶部。因此,大多数程序将手动将操作路由到较低的更新功能。这就是这里发生的事情。所有操作都必须进入 RandomGifPair.update
,并且由该函数决定 a) 调用子函数和 b) 将结果存储在状态中的正确位置。它可能会非常麻烦。
Here's the specific point in RandomGifPair.update
that does the routing。
第 42 行说“哦,这是一个 Left
动作?给我里面的 act
。现在你已经存储了你想要的 NewGif
或 RequestMore
在 act
、 和 中,您知道它绑定到左侧。第 44 行调用较低的更新函数,它知道如何处理。第 46 行存储结果模型中的下部更新函数(通过使用新的左侧和 re-using 旧的右侧重新创建整个模型)。
这一切都被 Effects 周围的样板所掩盖。如果你能先理解动作是如何流动的,然后回过头来将同样的逻辑应用到效果上,我想这会变得更清楚。
我可能来晚了一点,但效果很容易映射。
取值如下:
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)
Cmd.map 将顶级 Msg 映射到嵌套组件。想想蛇吃自己的尾巴。
在这个example (RandomGifPair)中,NewGif对应的update实际上是如何连接到父组件触发后执行的RandomGif.update act model.left
?似乎 RandomGif.update NewGif maybeUrl
需要在某处手动触发。更明确一点,RandomGifPair 触发其 Left 更新操作并通过手动调用 RandomGif 的更新函数取回模型/效果对。返回的效果通过Effects.map Left fx
执行,然后继续到RandomGif
getRandomGif : String -> Effects Action
getRandomGif topic =
Http.get decodeUrl (randomUrl topic)
|> Task.toMaybe
|> Task.map NewGif
|> Effects.task
据我所知,它将继续触发 NewGif 动作,由于 Effects.map,它现在也被标记为 Left。图片中我唯一缺少的部分是这个动作是如何保持在 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.update。可能不是尝试理解榆树的最佳方式...
所有操作都会进入您的 top-level 更新功能。无法将操作范围限定为 sub-update 函数 - 它们总是位于顶部。因此,大多数程序将手动将操作路由到较低的更新功能。这就是这里发生的事情。所有操作都必须进入 RandomGifPair.update
,并且由该函数决定 a) 调用子函数和 b) 将结果存储在状态中的正确位置。它可能会非常麻烦。
Here's the specific point in RandomGifPair.update
that does the routing。
第 42 行说“哦,这是一个 Left
动作?给我里面的 act
。现在你已经存储了你想要的 NewGif
或 RequestMore
在 act
、 和 中,您知道它绑定到左侧。第 44 行调用较低的更新函数,它知道如何处理。第 46 行存储结果模型中的下部更新函数(通过使用新的左侧和 re-using 旧的右侧重新创建整个模型)。
这一切都被 Effects 周围的样板所掩盖。如果你能先理解动作是如何流动的,然后回过头来将同样的逻辑应用到效果上,我想这会变得更清楚。
我可能来晚了一点,但效果很容易映射。
取值如下:
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)
Cmd.map 将顶级 Msg 映射到嵌套组件。想想蛇吃自己的尾巴。