榆树组件之间的沟通

时间:2016-03-30 18:24:31

标签: elm

假设我正在尝试遵循Elm架构,并在使用User时将我的工作流程拆分为InvoiceStartApp

用户有发票,但他们必须登录才能访问它们。

模型可能看起来像这样的东西:

type Model
   = NotLoggedIn Credentials
   | LoggedIn RealName (Maybe Invoices)

type alias State =
   { login : Model
   , notification : ......
   , ......


type alias Invoices = { invoices: List Invoice, ...... }

用户模块有操作:

type Action
   = Login (Result Http.Error String)
   | Logout
   | Submit
   ...

并更新功能:

update : Action -> Model -> (Model, Effects Action, Notification)
update action user =
   case (action, user) of
      (Login res, _) ->
         case res of
            Ok name ->
               (LoggedIn name Nothing, Effects.none, Info "Welcome!")
   ...

我跳过了身份验证的细节,这一切都很好。有趣的部分是Login动作。元组将发送到step中的main函数:

step : Action -> State -> (State, Effects Action)
step action state =
   case action of
      UserAction a ->
         let (newstate, ef, n) = User.update a state.login
         in ({ state | login = newstate, notification = n }, Effects.map UserAction ef)
      InvoiceAction a -> ......

因此用户已登录。接下来,我们要在init模块中调用一些Invoice操作。

但这应该怎样做呢?如何启动Invoice保护封装的行动?除了Effects.none之外我还要退还吗?

2 个答案:

答案 0 :(得分:4)

这可能是一个案例,可以通过应用程序数据的不同建模来解决。

我理解它的方式,您需要的操作需要用户和不需要用户的操作。 InvoiceAction告诉我它应该属于UserAction。

所以,你可以

type MainAction = UserAction UAction | NonUserAction NonUAction 

type UAction = AuthAction Credentials | InvoiceAction Invoice.Action

用户模型将封装登录详细信息和发票详细信息。然后,在成功登录后,您可以重定向到InvoiceAction。

update action model =
  case action of 
    AuthAction credentials -> 
      let 
        (isLoggedIn, notifications) = Authentication.check credentials
        model' = { model | credentials = credentials, notifications = notifications}
      in 
        if isLoggedIn
        then update (Invoice.initialize model'.credentials) model'
        else (model', Effects.none)

    InvoiceAction act -> 
      let 
        (invoices, fx) = Invoice.update model.credentials act model.invoices
      in 
        ({model | invoices = invoices}, Effects.map InvoiceAction fx)

实际操作由发票模块通过功能initialize提供,其签名为initialize: Credentials -> Action。这样做是为了保持封装。用户模块不需要知道特定的Invoice操作,只知道有一个与初始化有关,它可以通过该函数获取它。

另外,请注意我已简化更新签名并将通知移到模型中。这是个人偏好,因为我认为通知没有什么特别之处。它们就像模型中的任何其他数据一样。当然,如果通知是通过某个自定义StartApp路由到端口并通过某些JS机制显示的任务,那么将它们保留在返回中可能是有意义的。

答案 1 :(得分:2)

一种方法是:

  • 在父组件中创建邮箱
  • 将该邮箱的地址传递给User update
  • 用户更新返回向此地址发送消息的效果
  • 收到邮件后,此邮箱会触发流向Invoice
  • 的操作

elm-tutorial中的这一章显示了这种模式。