Cmd.map 是将 Elm SPA 拆分为模块的正确方法吗?
Is Cmd.map the right way to split an Elm SPA into modules?
我正在用 Elm 构建一个单页应用程序,但在决定如何在文件中拆分我的代码时遇到困难。
我最终使用每页 1 个模块将其拆分,并让 Main.elm
使用 Cmd.map
和 [=15= 转换每个页面发出的 Html
和 Cmd
].
我的问题是 Cmd.map 和 Html.map says that 的文档:
This is very rarely useful in well-structured Elm code, so definitely read the section on structure in the guide before reaching for this!
我检查了我所知道的仅有的 2 个大型应用程序:
- elm-spa-example 使用 Cmd.map (https://github.com/rtfeldman/elm-spa-example/blob/cb32acd73c3d346d0064e7923049867d8ce67193/src/Main.elm#L279)
- 我无法弄清楚 https://github.com/elm/elm-lang.org
处理这个问题。
此外, 的两个答案都建议使用 Cmd.map
,无需再三思。
Cmd.map 是在模块中拆分单个页面应用程序的“正确”方法吗?
我认为有时候您只需要做对适合您的事情。我对我编写的应用程序使用了 Cmd.map
/Sub.map
/Html.map
方法,该应用程序具有 3 个“页面”——初始化、编辑和报告。
我想让这些页面中的每一个都成为自己的模块,因为它们相对复杂,每个页面都有相当数量的消息,这些消息只与每个页面相关,并且更容易在每个页面自己的上下文中独立推理.
缺点是编译器不会阻止您收到给定页面的错误消息,从而导致运行时错误(例如,如果应用程序在 Reporting
页面,正确的行为是什么?对于我的具体实现,我只是将其记录到控制台并继续 - 这对我来说已经足够了(而且它从未发生过);我考虑过的其他选项包括显示一个讨厌的错误页面,表明发生了可怕的事情 - 如果你愿意的话,一个蓝屏死机;或者只是 reset/reinitialize 整个应用程序)。
另一种方法是使用 效果模式 ,如 this discourse post 中广泛描述的那样。
这种方法的核心是:
The extended Effect pattern used in this application consists in definining an Effect custom type that can represent all the effects that init and update functions want to produce.
主要好处:
- All the effects are defined in a single Effect module, which acts as an internal API for the whole application that is guaranteed to list every possible effect.
- Effects can be inspected and tested, not like Cmd values. This allows to test all the application effects, including simulated HTTP requests.
- Effects can represent a modification of top level model data, like the Session 3 when logging in 3, or the current page when an URL change is wanted by a subpage update function.
- All the update functions keep a clean and concise Msg -> Model -> ( Model, Effect Msg ) 2 signature.
- Because Effect values carry the minimum information required, some parameters like the Browser.Navigation.key are needed only in the effects perform 3 function, which frees the developer from passing them to functions all over the application.
- A single NoOp or Ignored String 25 can be used for the whole application.
我正在用 Elm 构建一个单页应用程序,但在决定如何在文件中拆分我的代码时遇到困难。
我最终使用每页 1 个模块将其拆分,并让 Main.elm
使用 Cmd.map
和 [=15= 转换每个页面发出的 Html
和 Cmd
].
我的问题是 Cmd.map 和 Html.map says that 的文档:
This is very rarely useful in well-structured Elm code, so definitely read the section on structure in the guide before reaching for this!
我检查了我所知道的仅有的 2 个大型应用程序:
- elm-spa-example 使用 Cmd.map (https://github.com/rtfeldman/elm-spa-example/blob/cb32acd73c3d346d0064e7923049867d8ce67193/src/Main.elm#L279)
- 我无法弄清楚 https://github.com/elm/elm-lang.org 处理这个问题。
此外,Cmd.map
,无需再三思。
Cmd.map 是在模块中拆分单个页面应用程序的“正确”方法吗?
我认为有时候您只需要做对适合您的事情。我对我编写的应用程序使用了 Cmd.map
/Sub.map
/Html.map
方法,该应用程序具有 3 个“页面”——初始化、编辑和报告。
我想让这些页面中的每一个都成为自己的模块,因为它们相对复杂,每个页面都有相当数量的消息,这些消息只与每个页面相关,并且更容易在每个页面自己的上下文中独立推理.
缺点是编译器不会阻止您收到给定页面的错误消息,从而导致运行时错误(例如,如果应用程序在 Reporting
页面,正确的行为是什么?对于我的具体实现,我只是将其记录到控制台并继续 - 这对我来说已经足够了(而且它从未发生过);我考虑过的其他选项包括显示一个讨厌的错误页面,表明发生了可怕的事情 - 如果你愿意的话,一个蓝屏死机;或者只是 reset/reinitialize 整个应用程序)。
另一种方法是使用 效果模式 ,如 this discourse post 中广泛描述的那样。
这种方法的核心是:
The extended Effect pattern used in this application consists in definining an Effect custom type that can represent all the effects that init and update functions want to produce.
主要好处:
- All the effects are defined in a single Effect module, which acts as an internal API for the whole application that is guaranteed to list every possible effect.
- Effects can be inspected and tested, not like Cmd values. This allows to test all the application effects, including simulated HTTP requests.
- Effects can represent a modification of top level model data, like the Session 3 when logging in 3, or the current page when an URL change is wanted by a subpage update function.
- All the update functions keep a clean and concise Msg -> Model -> ( Model, Effect Msg ) 2 signature.
- Because Effect values carry the minimum information required, some parameters like the Browser.Navigation.key are needed only in the effects perform 3 function, which frees the developer from passing them to functions all over the application.
- A single NoOp or Ignored String 25 can be used for the whole application.