elm-architecture 单独的信号处理?
elm-architecture separate signal handling?
我在网上找不到任何示例来回答这个问题:parent 组件如何响应来自 child 模块的不同操作?
考虑带有提交按钮的简单聊天消息输入:
// child 组件:带提交按钮的文本输入
type Action
= InputChanged String
| MessageSent String
view : Signal.Address Action -> Model -> Html
view addr model =
div []
[ input
[ type' "text"
, value model.content
, on "input" targetValue (\val -> Signal.message addr (InputChanged val))
]
[]
, button
[ type' "submit"
, onClick addr (MessageSent model.content)
]
[ text "Send" ]
]
持有此输入框的 parent 组件如何响应可能从该输入框发出的两个动作?传统的 "just passing through" 看起来像这样:
// parent 组件,保留帖子列表和 child 组件
-- update
type Action
= MessageBoxAction MessageBox.Action
update : Action -> Model -> Model
update act model =
case act of
MessageBoxAction msg ->
{ model |
currentMessage = MessageBox.update msg model.currentMessage
}
-- view
view : Signal.Address Action -> Model -> Html
view addr model =
div []
[ MessageBox.view (Signal.forwardTo addr MessageBoxAction) model.currentMessage ]
我想要做的是捕获来自该 child 组件的消息并在正常 "just passing through" 之外响应它。像这样:
case act of
MessageBoxSubmit msg ->
let updatedMessage = MessageBox.update msg model.currentMessage
newPost = Posts.update msg model.posts
in
{ model |
posts = model.posts :: [ newPost ]
, currentMessage = updatedMessage
}
但我不知道该怎么做,特别是因为在将地址转发给 child 时,您没有机会提供多个地址...
MessageBox.view (Signal.forwardTo addr MessageBoxAction) model.currentMessage
有两条主要途径可以做到这一点。
您可以将 MessageBox update
的签名更改为 return 您提供给 MessageBox init
的父操作 init
。
init : (String -> parentAction) -> Model
init onSend =
{ onSend = onSend
, content = ""
}
update : Action -> Model -> (Model, Maybe parentAction)
update action model =
case action of
MessageSent msg ->
let
model' = ...
in
(model', Just (model.onSend msg))
InputChanged str ->
let
model' = ...
in
(model', Nothing)
并在父模块中执行:
init =
{ posts = []
, currentMessage = MessageBox.init HandleSent
}
update : Action -> Model -> Model
update act model =
case act of
MessageBoxAction msg ->
let
(currentMessage', send) = MessageBox.update msg model.currentMessage
model' = {model | currentMessage = currentMessage'}
in
case send of
Nothing -> model'
Just act -> update act model' -- you recursively call the update function with the new action that you received from the MessageBox.update
HandleSent str -> { model | posts = str::model.posts }
- 您可以为 MessageBox 模块中的操作提供解码器。
在 MessageBox 模块中
sentMessage action =
case action of
MessageSent msg -> Just msg
_ -> Nothing
父
update : Action -> Model -> Model
update act model =
case act of
MessageBoxAction msg ->
let
currentMessage' = MessageBox.update msg model.currentMessage
model' = {model | currentMessage = currentMessage'}
in
case MessageBox.sentMessage msg of
Nothing -> model'
Just str -> update (HandleSent str) model'
HandleSent str -> { model | posts = str::model.posts }
我在网上找不到任何示例来回答这个问题:parent 组件如何响应来自 child 模块的不同操作? 考虑带有提交按钮的简单聊天消息输入:
// child 组件:带提交按钮的文本输入
type Action
= InputChanged String
| MessageSent String
view : Signal.Address Action -> Model -> Html
view addr model =
div []
[ input
[ type' "text"
, value model.content
, on "input" targetValue (\val -> Signal.message addr (InputChanged val))
]
[]
, button
[ type' "submit"
, onClick addr (MessageSent model.content)
]
[ text "Send" ]
]
持有此输入框的 parent 组件如何响应可能从该输入框发出的两个动作?传统的 "just passing through" 看起来像这样:
// parent 组件,保留帖子列表和 child 组件
-- update
type Action
= MessageBoxAction MessageBox.Action
update : Action -> Model -> Model
update act model =
case act of
MessageBoxAction msg ->
{ model |
currentMessage = MessageBox.update msg model.currentMessage
}
-- view
view : Signal.Address Action -> Model -> Html
view addr model =
div []
[ MessageBox.view (Signal.forwardTo addr MessageBoxAction) model.currentMessage ]
我想要做的是捕获来自该 child 组件的消息并在正常 "just passing through" 之外响应它。像这样:
case act of
MessageBoxSubmit msg ->
let updatedMessage = MessageBox.update msg model.currentMessage
newPost = Posts.update msg model.posts
in
{ model |
posts = model.posts :: [ newPost ]
, currentMessage = updatedMessage
}
但我不知道该怎么做,特别是因为在将地址转发给 child 时,您没有机会提供多个地址...
MessageBox.view (Signal.forwardTo addr MessageBoxAction) model.currentMessage
有两条主要途径可以做到这一点。
您可以将 MessageBox
update
的签名更改为 return 您提供给 MessageBoxinit
的父操作init
。init : (String -> parentAction) -> Model init onSend = { onSend = onSend , content = "" } update : Action -> Model -> (Model, Maybe parentAction) update action model = case action of MessageSent msg -> let model' = ... in (model', Just (model.onSend msg)) InputChanged str -> let model' = ... in (model', Nothing)
并在父模块中执行:
init =
{ posts = []
, currentMessage = MessageBox.init HandleSent
}
update : Action -> Model -> Model
update act model =
case act of
MessageBoxAction msg ->
let
(currentMessage', send) = MessageBox.update msg model.currentMessage
model' = {model | currentMessage = currentMessage'}
in
case send of
Nothing -> model'
Just act -> update act model' -- you recursively call the update function with the new action that you received from the MessageBox.update
HandleSent str -> { model | posts = str::model.posts }
- 您可以为 MessageBox 模块中的操作提供解码器。
在 MessageBox 模块中
sentMessage action =
case action of
MessageSent msg -> Just msg
_ -> Nothing
父
update : Action -> Model -> Model
update act model =
case act of
MessageBoxAction msg ->
let
currentMessage' = MessageBox.update msg model.currentMessage
model' = {model | currentMessage = currentMessage'}
in
case MessageBox.sentMessage msg of
Nothing -> model'
Just str -> update (HandleSent str) model'
HandleSent str -> { model | posts = str::model.posts }