一页如何发出消息以导航到Elm中的另一页?

时间:2018-06-24 04:15:40

标签: architecture navigation elm elm-architecture

我的Elm应用当前的结构如下:

Types.elm:

import Pages.Login.Types as Login
import Pages.Dashboard.Types as Dashboard

type Page = LoginPage
          | DashboardPage

type Msg = LoginMsg Login.Msg
         | DashboardMsg Dashboard.Msg
         | NavigationStart Page
         | NavigationEnd Page

type Model = LoginModel Login.Model
           | DashboardModel Dashboard.Model

Login.elm:

import Pages.Login.Types as PageTypes
import Types

view : (PageTypes.Msg -> msg) -> PageTypes.Model -> Html msg
view = -- some code 

我坚持以下看似竞争的要求:

  • 尝试使页面彼此之间完全独立,可以在页面上MsgModel类型进行独立推理
  • 使页面知道彼此的存在(在类型级别上),以便它们的视图/更新功能可以发出NavigationStart page消息,以在彼此之间导航。

在榆木中实现此目标的最佳方法是什么?

2 个答案:

答案 0 :(得分:2)

查看Richard Feldman的单页示例存储库here。本质上,您有一个顶级应用程序,该应用程序每页管理每个模型\视图\更新。

答案 1 :(得分:0)

如果您要从子页面的view发出顶级导航消息,则具体返回顶级消息类型没有什么问题,例如:

 view : Login.Model -> Html Types.Msg

如果您坚持按照指示抽象消息类型,则可以为导航消息传递一个额外的参数:

view : (Types.Page -> msg) -> (Login.Msg -> msg) -> Login.Model -> Html msg
view navigateTo wrapPageMsg model = ...

并使顶级视图函数将NavigationStart作为第一个参数传递。

最后,如果您需要子页面的update才能触发顶级导航,则可以将该信息放入返回值:

-- Login.update, updates the model and
-- optionally returns a navigation destination
update : Login.Msg -> Login.Model -> (Login.Model, Maybe Types.Page)

-- top level update
update : Msg -> Model -> Model
update msg model =
    let
        -- navigation helper
        navigateTo page model = ...
    in
    case (msg, model) of
        (NavigationStart p, _) ->
            navigateTo p model
        (LoginMsg lmsg, LoginModel lmodel) ->
            let
                (newlmodel, navigate) = Login.update lmsg lmodel
            in
            case navigate of
                Just p ->
                    navigateTo p model
                Nothing ->
                    LoginModel newlmodel
        ...

通常:可以根据您的特定需求为子页面调整视图类型和更新功能!