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

不幸的是,我在view中放入的所有内容都成为<body>的子级。从Html.body返回view并不能解决问题。这段代码:

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

view model = body [] []

update _ model = model

将产生:
<html>
    <head>...</head>
    <body>
        <body></body>
    </body>
</html>

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

最佳答案

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

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

port bodyKeyPress : (String -> msg) -> Sub msg

然后,您就可以通过javascript将按键发送到该端口:

app.ports.bodyKeyPress.send(...);

这是一个完整的例子:

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

以及幕后的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>

您将需要为每个要发送的主体事件创建并处理端口功能。

关于elm - 如何在Elm的body元素中添加事件处理程序?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39652083/

10-12 20:36