我正在阅读Elm guide和他们的JavaScript interOp。这是一个简化版本:
port module FooBar exposing (..)
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.App as Html
import String
main =
Html.program
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
}
-- subscriptions
port f : () -> Cmd msg
port g : ( Int -> msg ) -> Sub msg
subscriptions: Model -> Sub Msg
subscriptions model = g Get
-- MODEL
type alias Model = { pt : Int }
-- VIEW
view: Model -> Html Msg
view model = Html.text ( toString model.pt )
-- UPDATE
type Msg = Ask | Get Int
update: Msg -> Model -> (Model, Cmd msg)
update msg model =
case msg of
Ask -> (model, f () )
Get x -> ( Model x, Cmd.none )
-- INIT
init: (Model, Cmd Msg)
init = ( Model 0, f ())
该应用最初设置为 0 ,但它应该从JavaScript中读取消息并设置为 1 。但是,它仍然 0 。 Elm端口是否设置正确?
<div id="foobar"></div>
<script src="foo.js"></script>
<script>
var node = document.getElementById("foobar");
var app = Elm.FooBar.embed(node);
app.ports.f.subscribe(
function(){
var myValue = 1;
console.log(myValue);
app.ports.g.send(myValue);
}
);
</script>
</body>
我放在:elm-make foo.elm --output=foo.js
myValue
以 1 打印到控制台的事实表明已调用f()
端口,但g()
端口永远不会被回送或正确处理。
答案 0 :(得分:3)
很难判断这是否是一项设计决定,但在init
订阅任何端口之前调用了Html.App
。
因此,从f ()
调用init
将无效。
我使用send
函数,它运行一个虚拟任务并始终发送Ask
消息,这将触发传出端口。
考虑更改您的init
以发送将数据发送到端口的消息:
-- INIT
init : ( Model, Cmd Msg )
init =
-- ( Model 0, f ())
( Model 0, send Ask )
send : msg -> Cmd msg
send msg =
Task.perform identity identity (Task.succeed msg)
答案 1 :(得分:2)
如果您只想将Javascript中的默认值发送到您的Elm应用程序,则可以使用programWithFlags,无需尝试连接到尚未设置的端口:
main =
Html.programWithFlags
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
}
-- INIT
type alias Flags = { initialValue : Int }
init : Flags -> (Model, Cmd Msg)
init flags = ( Model flags.initialValue, Cmd.none )
这允许您通过Javascript发送该初始值,如下所示:
var app = Elm.FooBar.embed(node, { initialValue : 2 });