从这三个声明开始:
type SharedMsg
= SharedAction
type Page1Msg
= Page1Action
type Page2Msg
= Page2Action
我有办法获得相同的以下一个吗?就像一种“合并”联合类型的方式?
type Msg
= SharedAction
| Page1Action
| Page2Action
=============================
上下文:我将Elm应用程序拆分为每页一个模块,并带有自己的文件夹。
将共享某些操作,某些操作将特定于页面。
如果我要使用Html.map
方法,我觉得我必须重新编写页面在其自己的PageMsg
消息类型中使用的每个共享操作:
type Page1Msg
= Page1Action
| SharedAction
type Msg
= Page1Msg Page1Msg
| Page2Msg Page2Msg
view : Model -> Html Msg
view =
Html.map Page1Msg (Page1View.view model)
因此我考虑为所有页面使用唯一的Msg
类型,但通过在自己的文件夹中编写特定于页面的消息来保留模块性,然后通过合并它们以某种方式定义唯一的Msg
类型。
答案 0 :(得分:5)
@ z5h的回答几乎是正确的,但类型构造函数必须有不同的名称。
您无法按照自己喜欢的方式合并这些类型。
至于惯用方式:您只需将Msg
命名为拆分类型,而不是Page1Msg
。所以,例如:
<强> Page1.elm:强>
module Page1 exposing (Msg)
type Msg
= Foo
<强> Page2.elm:强>
module Page2 exposing (Msg)
type Msg
= Bar
<强> Shared.elm:强>
module Shared exposing (Msg)
type Msg
= Baz
<强> Main.elm:强>
module Main exposing (..)
import Shared
import Page1
import Page2
type Msg
= SomethingCustom
| SharedMsg Shared.Msg
| Page1Msg Page1.Msg
| Page2Msg Page2.Msg
顺便提一下,请记住,如果您将模块拆分为Page1.View
,Page1.Types
等,那么只要曝光的功能不重叠,您就可以导入不同的模块同名,即:
import Page1.Types as Page1
import Page1.State as Page1
import Page1.View as Page1
import Page1.Decoders as Page1
答案 1 :(得分:2)
不要忘记,您绝对没有义务完全按照基本示例中的更新视图定义。在您的情况下,您可以根据需要调整更新功能
在父母身上怎么样:
update message model =
let
sharedMsgs =
{ msg1 = Msg1
, msg2 = Msg2
}
in case message of
Page1Msg msg ->
let (m, c) =
update sharedMsgs msg model.page1
in case c of
Nothing ->
m
Just c ->
update c m
其中page1中的更新功能具有签名
update : SharedMessages msg -> Msg -> Page1Model -> (Page1Model, Maybe msg)
答案 2 :(得分:0)
问题是,你说过:
type SharedMsg
= SharedAction
因此我们知道SharedAction
的类型是SharedMsg
但是你说:
type Msg
= SharedAction
| Page1Action
| Page2Action
现在是一个矛盾,因为SharedAction
是Msg
。
解决这个问题的简单方法是:
type Msg
= Msg SharedMsg
| Msg Page1Msg
| Msg Page2Msg
即。 Msg
是一个构造函数,其实例的类型为Msg
,可以具有以下值。