从 Elm 读取全局 JavaScript 变量

Reading global JavaScript variable from Elm

我目前正在使用 Elm 构建网络应用程序的一个小组件。 elm 组件被编译为 JavaScript 文件,加载并挂载到 DOM 节点上。然后它应该从 window.config 读取一个配置对象。 (这不是我能改变的。)

我怎样才能从 window.config.title 中读取字符串以用于我的 Elm 组件?我查看了端口,但似乎需要我修改生成的 JavaScript 或将其包装起来。那是唯一的选择吗?如果是这样,我将如何简单地读取变量的值?

编辑:更新到 Elm 0.19

如果您的配置在您的应用程序的生命周期内没有改变,您可能最好使用 Browser.element or Platform.worker

这允许您的 main 函数在初始化期间接受来自 Javascript 的单个值。该单个值可以是一个简单的 javascript 对象,甚至可以包含嵌套属性。重要的是在 Elm 中定义它的形状。

假设您的 javascript 配置如下所示:

<script>
  window.options = {
    foo: 123,
    nested: { bar: "abc" }
  };
</script>

为了能够将其传递到您的 Elm 文件中,您可以定义一个匹配的形状,如下所示:

type alias Flags =
  { foo : Int
  , nested : { bar : String }
  }

现在您可以像这样在 Elm 文件中使用 Browser.elementPlatform.worker,定义一个将 Flags 作为参数的 init 函数:

import Html exposing (..)
import Browser
import String

main =
  Browser.element
    { init = init
    , view = view
    , update = update
    , subscriptions = subscriptions
    }

init : Flags -> (Model, Cmd Msg)
init flags =
  ( { introText = String.concat
    [ "foo is "
    , String.fromInt flags.foo
    , " and nested.bar is "
    , flags.nested.bar
    ]
    },
    Cmd.none
  )

最后一块拼图是在初始化期间将 Javascript 配置选项传递给 Elm。您的 html 和 javascript 应该看起来像这样(相关部分将 window.options 作为 init()flags 参数传递):

<body>
  <div id="myContainer"></div>
  <script src="Main.js"></script>
  <script>
    var app = Elm.Main.init( {
      node: document.getElementById("myContainer"),
      flags: window.options
    } );
  </script>
</body>

Here is a working example on ellie-app.