Elm Language
Hamnar (JS interop)
Sök…
Syntax
- Elm (mottagande): portfunktion Namn: (värde -> msg) -> Sub msg
- JS (skicka): app.ports.functionName.send (värde)
- Elm (sänder): portfunktion Namn: args -> Cmd msg
- JS (mottagande): app.ports.functionName.subscribe (funktion (args) {...});
Anmärkningar
Se http://guide.elm-lang.org/interop/javascript.html från Elm Guide för att hjälpa till att förstå dessa exempel.
Översikt
En modul, som använder hamnar ska ha port nyckelordet i den definition modul.
port module Main exposing (..)
Det är omöjligt att använda portar med Html.App.beginnerProgram , eftersom det inte tillåter att använda prenumerationer eller kommandon.
Portar är integrerade i för att uppdatera loopen av Html.App.program eller Html.App.programWithFlags .
Notera
program och programWithFlags i programWithFlags 0,18 finns i paketet Html istället för Html.App .
Utgående
Utgående portar används som kommandon som du kommer tillbaka från din update .
Elm sida
Definiera utgående port:
port output : () -> Cmd msg
I det här exemplet skickar vi en tom Tuple, bara för att utlösa ett prenumeration på JavaScript-sidan.
För att göra det måste vi tillämpa output med en tom Tuple som argument för att få ett kommando för att skicka utgående data från Elm.
update msg model =
case msg of
TriggerOutgoing data ->
( model, output () )
JavaScript-sida
Initiera applikationen:
var root = document.body;
var app = Elm.Main.embed(root);
Prenumerera på en port med motsvarande namn:
app.ports.output.subscribe(function () {
alert('Outgoing message from Elm!');
});
Notera
Från 0.17.0 har omedelbart utgående meddelande till JavaScript från ditt initial tillstånd ingen effekt.
init : ( Model, Cmd Msg )
init =
( Model 0, output () ) -- Nothing will happen
Se lösningen i exemplet nedan.
Inkommande
Inkommande data från JavaScript går via prenumerationer.
Elm sida
Först måste vi definiera en inkommande port med följande syntax:
port input : (Int -> msg) -> Sub msg
Vi kan använda Sub.batch om vi har flera prenumerationer, det här exemplet kommer bara att innehålla ett prenumeration till input port
subscriptions : Model -> Sub Msg
subscriptions model =
input Get
Sedan måste du skicka subscriptions till ditt Html.program :
main =
Html.program
{ init = init
, view = view
, update = update
, subscriptions = subscriptions
}
JavaScript-sida
Initiera applikationen:
var root = document.body;
var app = Elm.Main.embed(root);
Skicka meddelandet till Elm:
var counter = 0;
document.body.addEventListener('click', function () {
counter++;
app.ports.input.send(counter);
});
Notera
Observera att från och med 0.17.0 den omedelbara app.ports.input.send(counter); efter appinitiering har ingen effekt!
Vidarebefordra alla nödvändiga data för uppstarten som flaggor med Html.programWithFlags
Omedelbart utgående meddelande vid start i 0.17.0
För att skicka ett omedelbart meddelande med data till JavaScript måste du utlösa en åtgärd från din init .
init : ( Model, Cmd Msg )
init =
( Model 0, send SendOutgoing )
send : msg -> Cmd msg
send msg =
Task.perform identity identity (Task.succeed msg)
Komma igång
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Trying out ports</title>
</head>
<body>
<div id="app"></div>
<script src="elm.js"></script>
<script>
var node = document.getElementById('app');
var app = Elm.Main.embed(node);
// subscribe to messages from Elm
app.ports.toJs.subscribe(function(messageFromElm) {
alert(messageFromElm);
// we could send something back by
// app.ports.fromJs.send('Hey, got your message! Sincerely, JS');
});
// wait three seconds and then send a message from JS to Elm
setTimeout(function () {
app.ports.fromJs.send('Hello from JS');
}, 3000);
</script>
</body>
</html>
Main.elm
port module Main exposing (..)
import Html
port toJs : String -> Cmd msg
port fromJs : (String -> msg) -> Sub msg
main =
Html.program
{ init = (Nothing, Cmd.none) -- our model will be the latest message from JS (or Nothing for 'no message yet')
, update = update
, view = view
, subscriptions = subscriptions
}
type Msg
= GotMessageFromJs String
update msg model =
case msg of
GotMessageFromJs message ->
(Just message, toJs "Hello from Elm")
view model =
case model of
Nothing ->
Html.text "No message from JS yet :("
Just message ->
Html.text ("Last message from JS: " ++ message)
subscriptions model =
fromJs GotMessageFromJs
Installera paketet elm-lang/html om du ännu inte har elm-package install elm-lang/html --yes .
Kompilera denna kod med elm-make Main.elm --yes --output elm.js så att HTML-filen hittar den.
Om allt går bra, bör du kunna öppna filen index.html med texten "Inget meddelande". Efter tre sekunder skickar JS ett meddelande, Elm får det, byter modell, skickar ett svar, JS får det och öppnar en varning.