2

在 elm 中,您可以将标志传递给 elm 应用程序,如下所示:

网页/JS

  <div id="elm"></div>
  <script>
var app = Elm.Main.init({
  node: document.getElementById('elm'),
  flags: Date.now()
});
  </script>

然后 elm 应用程序在 init 上获取参数:

init : Int -> ( Model, Cmd Msg )
init currentTime =
  ...

我已经阅读了寓言文档,对我来说尚不清楚如何实现同样的目标。

我看到有一个选项 Program.runWith 可以在 init 函数上发送参数,但我找不到文档,也无法从编译的 javascript 中看到我应该如何从 html 文件调用主函数。

对于寓言,我希望能够在 html 文件中执行类似的操作,但不确定“Program.Run ..”是什么:

<body>
    <div id="elmish-app" class="elmish-app"></div>
    <script src="bundle.js"></script>
    <script>
        Program.Run({time: Date.now()});
    </script>
</body>

谢谢

4

2 回答 2

2

创建 Elmish 时Program,您可以使用|> Program.runWith它来传递初始参数。

type Model =
    { Value : string }

let init (initial : string) = { Value = initial }, Cmd.none

Program.mkProgram init update view
|> Program.withReact "elmish-app"
|> Program.runWith "My initial value"

请注意,initialininit是一个字符串,因为它接收 的参数Program.runWith

为了公开 API,在您的浏览器中,hacky方法是执行以下操作:

open Fable.Core.JsInterop

let private startApplication arg =
    Program.mkProgram init update view
    |> Program.withReact "elmish-app"
    |> Program.runWith arg

Fable.Import.Browser.window?startApplication <- startApplication

startApplication因此,您要在全局范围内设置注册函数window

更简洁的解决方案是使用 configurewebpack以使其生成一个库并在window范围内为您注册它。

在您的 webpack.config.js 中,您的输出节点应如下所示:

    output: {
        path: resolve('./output'),
        filename: '[name].js',
        libraryTarget: 'var',
        library: 'Program'
    },

然后在您的代码中使用一个接口来公开一个 JavaScript 友好的 API:

type MyApp =
    abstract Run : string -> unit

let api =
    { new MyApp with
        member __.Run arg = startApplication arg
    }

现在您可以使用 JavaScript 从 JavaScript 调用它Program.api.Run("initial value")

于 2019-01-31T18:52:44.210 回答
0

只是基于 Maxime Mangel 的早期答案,我采用了 hacky 方法,但对其进行了一些调整以使用 local storage。我要分享的是,对于需要找到一种方法将 Args 传递给在开始之前设置/收集的 Fable-Elmish 应用程序的任何其他人来说,这是一个替代方案。

在 App.fs 中(最后一个文件运行/编译):

let initialArgs = {
    Sender = Browser.Dom.window.localStorage.getItem("Sender")
    HubConnectionURI = Browser.Dom.window.localStorage.getItem("ServiceURI")}

let startApplication args = 
    Program.mkSimple init update view
    |> Program.withReactSynchronous "elmish-app"
    |> Program.withSubscription Subscription.hubConnection
    |> Program.withConsoleTrace
    |> Program.runWith args

do startApplication initialArgs

这从应用程序初始化之前在浏览器中设置的本地存储值中提取,因此您可以在 JS 中设置这些值,但是,您愿意。

在 index.html 中:

<body>
    <div id="elmish-app" class="elmish-app"></div>
    <script>
      window.localStorage.setItem('Sender', 'Chairman Meow')
      window.localStorage.setItem('ServiceURI', 'http://localhost:7071')
    </script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/microsoft-signalr/3.1.3/signalr.min.js"></script>
    <script src="bundle.js"></script>
</body>

您当然可以调整它,但是您想提取在本地存储中设置的值/变量。我需要这些“动态”初始参数来参数化我想在程序运行中启动的订阅,并将其用于我正在为在 Fable-Elmish 中使用 SignalR 进行的演示,我可能会对此进行调整以提示这些在加载页面时。

然而,这里的重点是你可以做任何你想做的事情来获取值,只要它们在应用程序启动之前设置在本地存储中!我发现这是一个相对“更干净的黑客”,但我仍然是 Fable-Elmish 的初学者,并且可能有更好的方法。

[只是想更清楚地强调这些将成为初始模型的一部分]

于 2020-05-11T22:11:42.410 回答