标记
标记是在初始化时将值传递到 Elm 的一种方式。
常见用途包括传递 API 密钥、环境变量和用户数据。如果您动态生成 HTML,这会很方便。它们还可以帮助我们在此 localStorage
示例 中加载缓存信息。
HTML 中的标记
HTML 与之前基本相同,但向 Elm.Main.init()
函数添加了一个 flags
参数
<html>
<head>
<meta charset="UTF-8">
<title>Main</title>
<script src="main.js"></script>
</head>
<body>
<div id="myapp"></div>
<script>
var app = Elm.Main.init({
node: document.getElementById('myapp'),
flags: Date.now()
});
</script>
</body>
</html>
在此示例中,我们传递的是以毫秒为单位的当前时间,但任何可以 JSON 编码的 JS 值都可以作为标记提供。
注意:这些附加数据称为“标记”,因为它有点儿像命令行标记。您可以调用
elm make src/Main.elm
,但可以添加一些标记,例如--optimize
和--output=main.js
,以自定义其行为。同样的大致意思。
Elm 中的标记
要在 Elm 侧处理标记,您需要对 init
函数稍加修改
module Main exposing (..)
import Browser
import Html exposing (Html, text)
-- MAIN
main : Program Int Model Msg
main =
Browser.element
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
}
-- MODEL
type alias Model = { currentTime : Int }
init : Int -> ( Model, Cmd Msg )
init currentTime =
( { currentTime = currentTime }
, Cmd.none
)
-- UPDATE
type Msg = NoOp
update : Msg -> Model -> ( Model, Cmd Msg )
update _ model =
( model, Cmd.none )
-- VIEW
view : Model -> Html Msg
view model =
text (String.fromInt model.currentTime)
-- SUBSCRIPTIONS
subscriptions : Model -> Sub Msg
subscriptions _ =
Sub.none
这里唯一重要的是 init
函数表明它采用一个 Int
参数。这就是 Elm 代码如何立即访问您从 JavaScript 中传递的标记的方式。在此基础上,您可以将内容放在模型中或运行某些命令。无论您需要做什么都可以。
我建议查看 此 localStorage
示例,以了解标记的更有趣用法!
验证标记
但是,如果 init
表明它采用一个 Int
标记,但有人尝试使用 Elm.Main.init({ flags: "haha, what now?" })
进行初始化,会怎样?
Elm 会检查此类内容,以确保标记完全符合您的预期。如果没有此检查,您可以传入任何内容,从而导致 Elm 中出现运行时错误!
有一些类型可以作为标记提供
布尔值
Int
Float
String
也许
List
Array
- 元组
- 记录
Json.Decode.Value
很多人经常使用 Json.Decode.Value
,因为它能让他们拥有精准的控制。他们可以用 Elm 代码编写一个解码器来处理任何出错的情况,能很好地从意外数据中恢复过来。
其他受支持的类型实际上早于我们找到 JSON 解码器的方法时就已经有了。如果您选用它们,有一些细微之处需要了解。以下示例展示了期望的标志类型,接下来的小节则展示了如果使用两个不同的 JS 值会发生什么
init : Int -> ...
0
=>0
7
=>7
3.14
=> error6.12
=> error
init : Maybe Int -> ...
null
=>Nothing
42
=>Just 42
"hi"
=> error
init : { x : Float, y : Float } -> ...
{ x: 3, y: 4, z: 50 }
=>{ x = 3, y = 4 }
{ x: 3, name: "Tom" }
=> error{ x: 360, y: "why?" }
=> error
init : (String, Int) -> ...
["Tom", 42]
=>("Tom", 42)
["Sue", 33]
=>("Sue", 33)
["Bob", "4"]
=> error["Joe", 9, 9]
=> error
请注意,当某个转换出错时,您将在 JS 侧遇到错误!我们采取了“尽早失败”策略。错误不会进入 Elm 代码,而是在及早阶段报告。这也是人们喜欢对标志使用 Json.Decode.Value
的另一个原因。异常值会通过解码器,而不是在 JS 中遇到错误,这可以确保您实施某种回退行为。