假设我正在尝试遵循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)
所以用户已登录.接下来我们要init在Invoice模块中调用一些操作.
但是如何做到这一点呢?如何启动Invoice保护封装的行动?除了以外我还能回复Effects.none吗?
这可能是可以通过应用程序数据的不同建模来解决的情况。
据我理解,您有需要用户的操作和不需要用户的操作。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 机制显示的任务,则将它们保留在返回中可能是有意义的。