榆树组件和视图:当我们应该使用`Html msg`和何时使用`Html Msg`

时间:2017-09-04 10:45:43

标签: elm

我正在研究一个项目和我的队友,我正在讨论哪种方法更好。

在我看来,Html msg似乎更通用,所以我认为我们应该尽可能地使用它,但我不能给他其他理由。

此外,我来自React和Redux,对我看起来像签名Html Msg的组件就是我们所谓的Smart/Connected ComponentsHtml msg就像{{1}我对这个假设是对的吗?

你能告诉我什么时候应该使用每一个吗?

谢谢

2 个答案:

答案 0 :(得分:6)

将视图函数注释为返回Html msg意味着您没有将视图绑定到特定的Msg类型。因此,它更灵活,但它也限制了你可以做的事情。

在编写不呈现特定于Msg特定代码的共享代码时,使用小写版本很有用。例如,您可以标准化一些布局代码:

pageTitle : String -> Html msg
pageTitle title =
    h1 [ class "page-title" ] [ text title ]

上面的代码可以返回Html Msg,但这会限制它分享它的能力,因为你将它绑定到特定的Msg类型。

现在,如果您正在编写能够生成特定事件并将其绑定到Msg构造函数的内容,那么您必须返回Html Msg

type Msg = RollDice | Rolled Int

diceButton : String -> Html Msg
diceButton label =
    button [ class "fancy-btn", onClick RollDice ] [ text label ]

如果您尝试返回小写Html msg,则无法编译上述定义。

如果我们停在那里,我可以看到这可能会如何与React中的智能与愚蠢的组件概念相似,因为看似小写的版本无法呈现会引发事件的Html,但这个类比并不是'真的抱着。假设您希望在系统范围内标准化按钮,但不希望将其与特定Msg绑定。您可以通过接受点击时触发的Msg参数来使函数更通用。

fancyButton : String -> msg -> Html msg
fancyButton label msg =
    button [ class "fancy-btn", onClick msg ] [ text label ]

通常,如果您要编写要在内部或作为外部包共享的代码,则可以通过使用小型版Html msg来提供更大的灵活性。这样做,您仍然可以编写可以触发事件的Html,就像在上面的fancyButton示例中一样,它只是意味着您将一些责任传递给调用函数,而调用函数必须决定{{1}传入。

答案 1 :(得分:1)

msgMsg确实是根本不同的种类m / M是大写或小写的事实!

用户定义的类型

type Msg = RollDice | Rolled Int正在定义类型,该类型特定于您的计划。你可以随意调用它(只要用大写字母开头)。事实上,Msg在这里真的是一个可怕的名字 - 这些消息是关于什么的?我不知道!

相反:type DiceMsg = RollDice | Rolled Int。啊 - 现在我明白了,这是一个关于骰子的类型(消息)。得到它了! :)

也许你的程序也有:

type Suit = Spades | Hearts | Clubs | Diamonds
type CardMsg = DrawCard | CardDrawn Suit Int

然后你可以看到有什么区别:

Html DiceMsg - 这是一些会产生关于骰子的消息。

Html CardMsg - 这是一些会产生卡片消息的HTML。

多个用户定义类型

一起使用的代码

现在让我们考虑像h1 [ class "page-title" ] [ text title ]这样的html。 html的是什么?

您可以看到它根本不会产生任何消息,因此将其称为Html DiceMsg Html CardMsg并不合理。但是,它可以组成任何类型的HTML,对吗?您可以将Html DiceMsg块上方的标题设置为{<1}},然后您将获得更大的 Html DiceMsg块。

这就是Html msg(小写m)的含义:小写msg表示“它可以是任何东西,让编译器弄明白”。编译器将根据您使用它的上下文决定msgDiceMsg的占位符还是CardMsg的占位符。 (用技术术语来说,msg类型变量。)

使用msg

进行参数化

为了获得最大的灵活性,您可以让函数的调用者控制他们希望您的代码生成哪种消息:

fancyButton : String -> msg -> Html msg
fancyButton label msg =
    button [ class "fancy-btn", onClick msg ] [ text label ]

此处,msg 一个参数类型和返回类型。因此编译器可以发现fancyButton "draw a card" DrawCard之类的调用会产生Html CardMsg,而fancyButton "roll the dice" RollDice会产生Html DiceMsg