Elm 端口如何工作,附图片(仅一张)
Elm 端口如何工作,附图片(仅一张)
原文:https://medium.com/hackernoon/how-elm-ports-work-with-a-picture-just-one-25144ba43cdd
Elm ports 是与 JavaScript 交互的主要方式之一。然而,我觉得我需要告诉你,如果你可以逃脱,你应该只使用旗帜。标志传递一些初始值给 Elm,这无疑是最简单的方法。然而,如果你想要更多的来回通信端口的方式。
高级概述
首先,这是图片:

端口基本上是发布-订阅模式(也称为观察者模式)。端口是 Elm 和 JavaScript 之间的连接管道。
每个端口只有一个方向。不是 Elm ->JavaScript 就是 JavaScript -> Elm。所以自然地,如果你想要双向交流,你只需要做两个。
制作端口
一些设置
如果你打算继续做下去,请遵循这些步骤(或者也许只要看看代码)
步骤 1: 用完整的Html.program建立一个Main.elm文件
第二步:一个.js文件,暂时可以为空
第三步:一个index.html文件,包括elm.js(编译的 elm 文件)和whatever.js文件,后者包含你想要交互的代码。
从 Elm 到 JavaScript
在模块的开头加上一个port来注释模块
- 创建一个到 JavaScript的端口,其类型签名如下**
*port **toJs** : String -> Cmd msg*
这将创建一个名为toJs的函数,该函数创建Cmd s(命令)。如果你记得你可以在update函数中返回Cmd作为元组的第二部分!就这么办吧。
*update msg model =
case msg of SendToJs str ->
( model, **toJs** *str* )*
这将神奇地把`str`发送到 JavaScript 的土地!只对订阅它的人开放。要订阅它,您需要:
*var node = document.getElementById('view');
var app = Elm.Main.embed(node);// receive something from Elm
**app.ports.toJs.subscribe**(function (*str*) {
console.log("got from Elm:", *str*);
});*
从 JavaScript 到 Elm
*在 JS 土地上你 通过端口上的send方法发送 的东西。像这样:*
*var node = document.getElementById('view');
var app = Elm.Main.embed(node);
app.ports.**toElm.send**("undefined is not a function");*
自然 JS 说是习惯用语。
所以我们定义了一个新的端口:
*port toElm : (String -> msg) -> Sub msg*
这就创建了一个函数,接受一个函数,这个函数可以将 JS 发送的字符串转换成一个Msg(也可以是两者兼容的任何值)这个函数返回一个Sub而不是一个Cmd,所以我们需要在 Elm 中为订阅:
*subscriptions : Model -> Sub Msg
subscriptions model =
toElm UpdateStr*
基本上这是说:
每当 JS 通过 `toElm` 端口向我发送东西时,就向 `update` 函数发送 `UpdateStr` 消息。
我们可以像处理 update 函数中的其他函数一样处理这个Msg:
*update msg model =
case msg of
UpdateStr str ->
( { model | message = str }, Cmd.none )*
基本上我只是把 JS 给我的字符串存储到我的模型的一部分。
🚨警告:运行时异常提前!🚨
虽然我使用了String来保持简单,但这是危险的。
如果 JavaScript(以其无限的智慧)决定发送一个不是字符串的东西(比如 null、undefined、NaN、rubber duck、a function 等等)。)然后 Elm 将抛出一个运行时异常并停止它的运行循环。
这意味着 Elm 将不能接受任何输入或以任何方式响应。死了。**
使你的 elm 代码再次防弹的方法改为将端口的类型改为Value。这意味着你必须写一个 Json。它的解码器。这样,如果 JS 决定给你发送一个错误的值,它只会返回一个Err 而不是抛出一个异常。
请参见此处的差异
*import Json.Encode exposing (Value)
import Json.Decode as Decode-- Farther down in the file.... --port toElm : (**Value** -> msg) -> Sub msg-- SUBSCRIPTIONSsubscriptions : Model -> Sub Msg
subscriptions model =
toElm (**decodeValue**)decodeValue : Value -> Msg
decodeValue x =
let
result =
**Decode.decodeValue Decode.string x**
in
case result of
Ok string ->
UpdateStr string Err _ ->
UpdateStr "Silly JavaScript, you can't kill me!"*
就是这样!
图片又来了:

这里有一个工作回购的链接:https://github.com/justgage/complete-elm-port-example



