榆树架构独立信号处理?

时间:2016-02-21 01:51:35

标签: elm

我无法在网上任何地方找到一个回答问题的例子:父组件如何响应来自子模块的不同操作? 考虑使用提交按钮的简单聊天消息输入:

//子组件:带提交按钮的文本输入

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" ]
        ]

保留在此输入框中的父组件如何响应可能来自该输入框的两个操作?传统的"只是通过"看起来像这样:

//父组件,保留在帖子列表和子组件

-- 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 ]

我希望能够捕获来自该子组件的消息,并在正常情况下对其做出响应"只是通过"。像这样:

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
            }

但我不知道如何做到这一点,特别是因为在将地址转发给孩子时,并不是说你有机会提供多个地址......

MessageBox.view (Signal.forwardTo addr MessageBoxAction) model.currentMessage

1 个答案:

答案 0 :(得分:1)

有两条主要路线可以做到这一点。

  1. 您可以更改MessageBox update的签名,以返回您向MessageBox 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)
    
  2. 并在父模块中执行:

    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 }           
    
    1. 您可以在MessageBox模块中为操作提供解码器。
    2. 消息框模块中的

      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 }