Elm 组件和视图:何时应该使用 `Html msg` 以及何时使用 `Html Msg`
Elm components and views: When we should use `Html msg` and when `Html Msg`
我正在做一个项目,我和我的队友正在讨论哪种方法更好。
在我看来Html msg
似乎更通用,所以我认为我们应该尽可能使用它,但我不能给他其他理由。
此外,我来自 React 和 Redux,在我看来,带有签名 Html Msg
的组件就是我们所说的 Smart/Connected Components
和 Html msg
就像 Dumb Components
,我这个假设对吗?
你能告诉我什么时候应该使用每一个吗?
谢谢
将视图函数注释为 returning Html msg
意味着您没有将视图绑定到特定的 Msg
类型。因此它更加灵活,但它也限制了您可以做的事情。
在编写不呈现任何特定于特定 Msg
的代码的共享代码时,使用小写版本很有用。例如,您可以标准化一些布局代码:
pageTitle : String -> Html msg
pageTitle title =
h1 [ class "page-title" ] [ text title ]
上面的代码可以returnHtml Msg
但是这会限制它的共享能力,因为你会把它绑定到一个特定的Msg
类型。
现在,如果您正在编写能够生成特定事件的东西并将其绑定到 Msg
构造函数,那么您必须 return Html Msg
:
type Msg = RollDice | Rolled Int
diceButton : String -> Html Msg
diceButton label =
button [ class "fancy-btn", onClick RollDice ] [ text label ]
如果您尝试 return 小写 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
示例一样,这只是意味着您将一些责任传递给调用函数,它必须决定什么Msg
传入。
msg
和Msg
确实是根本不同的种类。 m
/M
是大写还是小写很重要!
User-defined 类型
type Msg = RollDice | Rolled Int
正在定义 new 类型,该类型特定于 您的程序 。您可以随意命名(只要以大写字母开头)。事实上,Msg
在这里真的是一个可怕的名字——这些消息是关于什么的?我不知道!
而是:type DiceMsg = RollDice | Rolled Int
。啊——现在我明白了,这是一个关于骰子的类型(消息)。知道了! :)
也许你的程序还有:
type Suit = Spades | Hearts | Clubs | Diamonds
type CardMsg = DrawCard | CardDrawn Suit Int
那你就知道有什么区别了:
Html DiceMsg
-- 这是一些 html 会产生关于骰子的信息。
Html CardMsg
-- 这是一些 html 会产生关于卡片的信息。
适用于 多种 user-defined 类型的代码
现在让我们像 h1 [ class "page-title" ] [ text title ]
一样考虑 html。 html 的 种类 是什么?
你可以看到它根本不产生任何消息,所以称它为Html DiceMsg
或[=20=真的没有意义].但是,它可以 与 任何一种 html 组合,对吧?您可以将这样的标题放在 Html DiceMsg
块上方,然后您会得到... 更大的 Html DiceMsg
.
块
所以这就是 Html msg
(lower-case m
) 的意思:lower-case msg
的意思是“它可以是任何东西,让编译器想办法”。编译器将根据您使用它的上下文来决定 msg
是 DiceMsg
的占位符还是 CardMsg
的占位符。 (在技术术语中,msg
是一个 类型变量 。)
参数化 msg
为了获得最大的灵活性,您可以让函数的调用者控制他们希望您的代码生成哪种消息:
fancyButton : String -> msg -> Html msg
fancyButton label msg =
button [ class "fancy-btn", onClick msg ] [ text label ]
这里,msg
是既是又是return类型的参数类型。所以编译器可以计算出像 fancyButton "draw a card" DrawCard
这样的调用会产生 Html CardMsg
,而 fancyButton "roll the dice" RollDice
会产生 Html DiceMsg
.
我正在做一个项目,我和我的队友正在讨论哪种方法更好。
在我看来Html msg
似乎更通用,所以我认为我们应该尽可能使用它,但我不能给他其他理由。
此外,我来自 React 和 Redux,在我看来,带有签名 Html Msg
的组件就是我们所说的 Smart/Connected Components
和 Html msg
就像 Dumb Components
,我这个假设对吗?
你能告诉我什么时候应该使用每一个吗?
谢谢
将视图函数注释为 returning Html msg
意味着您没有将视图绑定到特定的 Msg
类型。因此它更加灵活,但它也限制了您可以做的事情。
在编写不呈现任何特定于特定 Msg
的代码的共享代码时,使用小写版本很有用。例如,您可以标准化一些布局代码:
pageTitle : String -> Html msg
pageTitle title =
h1 [ class "page-title" ] [ text title ]
上面的代码可以returnHtml Msg
但是这会限制它的共享能力,因为你会把它绑定到一个特定的Msg
类型。
现在,如果您正在编写能够生成特定事件的东西并将其绑定到 Msg
构造函数,那么您必须 return Html Msg
:
type Msg = RollDice | Rolled Int
diceButton : String -> Html Msg
diceButton label =
button [ class "fancy-btn", onClick RollDice ] [ text label ]
如果您尝试 return 小写 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
示例一样,这只是意味着您将一些责任传递给调用函数,它必须决定什么Msg
传入。
msg
和Msg
确实是根本不同的种类。 m
/M
是大写还是小写很重要!
User-defined 类型
type Msg = RollDice | Rolled Int
正在定义 new 类型,该类型特定于 您的程序 。您可以随意命名(只要以大写字母开头)。事实上,Msg
在这里真的是一个可怕的名字——这些消息是关于什么的?我不知道!
而是:type DiceMsg = RollDice | Rolled Int
。啊——现在我明白了,这是一个关于骰子的类型(消息)。知道了! :)
也许你的程序还有:
type Suit = Spades | Hearts | Clubs | Diamonds
type CardMsg = DrawCard | CardDrawn Suit Int
那你就知道有什么区别了:
Html DiceMsg
-- 这是一些 html 会产生关于骰子的信息。
Html CardMsg
-- 这是一些 html 会产生关于卡片的信息。
适用于 多种 user-defined 类型的代码
现在让我们像 h1 [ class "page-title" ] [ text title ]
一样考虑 html。 html 的 种类 是什么?
你可以看到它根本不产生任何消息,所以称它为Html DiceMsg
或[=20=真的没有意义].但是,它可以 与 任何一种 html 组合,对吧?您可以将这样的标题放在 Html DiceMsg
块上方,然后您会得到... 更大的 Html DiceMsg
.
所以这就是 Html msg
(lower-case m
) 的意思:lower-case msg
的意思是“它可以是任何东西,让编译器想办法”。编译器将根据您使用它的上下文来决定 msg
是 DiceMsg
的占位符还是 CardMsg
的占位符。 (在技术术语中,msg
是一个 类型变量 。)
参数化 msg
为了获得最大的灵活性,您可以让函数的调用者控制他们希望您的代码生成哪种消息:
fancyButton : String -> msg -> Html msg
fancyButton label msg =
button [ class "fancy-btn", onClick msg ] [ text label ]
这里,msg
是既是又是return类型的参数类型。所以编译器可以计算出像 fancyButton "draw a card" DrawCard
这样的调用会产生 Html CardMsg
,而 fancyButton "roll the dice" RollDice
会产生 Html DiceMsg
.