如何在Elm中的body元素中添加事件处理程序?

Min*_*oru 5 elm

我正在尝试使用Html.App.beginnerProgram,我想onKeyDown<body>元素中添加事件处理程序(等).

不幸的是,我投入的一切都view变成了孩子们<body>.返回Html.bodyview不会做的伎俩.这段代码:

main = beginnerProgram { model = 0, view = view, update = update }

view model = body [] []

update _ model = model
Run Code Online (Sandbox Code Playgroud)

会产生:

<html>
    <head>...</head>
    <body>
        <body></body>
    </body>
</html>
Run Code Online (Sandbox Code Playgroud)

那么,我如何获得<body>元素的控制权?

Cha*_*ert 6

由于Elm呈现为后代<body/>,因此您无法以正常的Elm方式将事件处理绑定到它(例如button [ onClick SomeMsg ] []).相反,你将不得不使用端口.而且因为您正在使用端口和订阅,所以您需要使用Html.App.program而不是beginnerProgram.

您需要在端口模块中使用端口功能:

port bodyKeyPress : (String -> msg) -> Sub msg
Run Code Online (Sandbox Code Playgroud)

然后你就可以从javascript向该端口发送按键了:

app.ports.bodyKeyPress.send(...);
Run Code Online (Sandbox Code Playgroud)

这是一个完整的例子:

Main.elm

port module Main exposing (main)

import Html.App as App
import Html exposing (..)

main = App.program
  { init = init
  , update = update
  , view = view
  , subscriptions = subscriptions
  }

type alias Model = { message : String } 

type Msg = BodyKeyPress String

init = { message = "Press some keys: " } ! []

update msg model =
  case msg of
    BodyKeyPress c ->
      { model | message = model.message ++ c } ! []

view model = text model.message

subscriptions _ =
  bodyKeyPress BodyKeyPress

port bodyKeyPress : (String -> msg) -> Sub msg
Run Code Online (Sandbox Code Playgroud)

幕后的html(假设你使用了elm make Main.elm --output=Main.js):

<html>
  <body>
    <script src="Main.js"></script>
    <script>
      var app = Elm.Main.fullscreen();

      document.body.onkeypress = function(e) {
        app.ports.bodyKeyPress.send(String.fromCharCode(e.keyCode));
      };
    </script>
  </body>
</html>
Run Code Online (Sandbox Code Playgroud)

您需要为要发送的每个正文事件创建和处理端口函数.