榆树组件之间的通信

pun*_*und 5 elm

假设我正在尝试遵循Elm架构并在使用时将我的工作流分为Users和Invoices StartApp.

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

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

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

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


type alias Invoices = { invoices: List Invoice, ...... }
Run Code Online (Sandbox Code Playgroud)

用户模块有动作:

type Action
   = Login (Result Http.Error String)
   | Logout
   | Submit
   ...
Run Code Online (Sandbox Code Playgroud)

和更新功能:

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!")
   ...
Run Code Online (Sandbox Code Playgroud)

我跳过了身份验证的细节,这一切都很好.有趣的是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 -> ......
Run Code Online (Sandbox Code Playgroud)

所以用户已登录.接下来我们要initInvoice模块中调用一些操作.

但是如何做到这一点呢?如何启动Invoice保护封装的行动?除了以外我还能回复Effects.none吗?

pda*_*moc 4

这可能是可以通过应用程序数据的不同建模来解决的情况。

据我理解,您有需要用户的操作和不需要用户的操作。InvoiceAction 给我的感觉是它应该属于 UserAction。

所以,你可以有

type MainAction = UserAction UAction | NonUserAction NonUAction 

type UAction = AuthAction Credentials | InvoiceAction Invoice.Action
Run Code Online (Sandbox Code Playgroud)

用户模型将封装登录详细信息和发票详细信息。然后,成功登录后,您可以重定向到 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)
Run Code Online (Sandbox Code Playgroud)

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

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