如何使用带有寓言的Elmish将参数从html页面传递到已编译的js应用程序

时间:2018-11-16 10:40:09

标签: ffi fable-f# elmish

在elm中,您可以像这样将标志传递给elm应用程序:

HTML / 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文件调用主函数。 / p>

有了寓言,我希望能够在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>

谢谢

2 个答案:

答案 0 :(得分:0)

创建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"

请注意,initial中的init是一个字符串,因为它接收到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函数。

一个更干净的解决方案是使用configure webpack,以便使其生成一个库并在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
    }

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

从JavaScript调用它了

答案 1 :(得分:0)

只是基于马克西姆·曼格尔(Maxime Mangel)先前的回答, 我采用了骇人听闻的方法,但是在使用本地存储方面做了一些调整 。我要分享的是,对于任何其他需要找到将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的初学者,并且可能有更好的方法。

[为了进一步清楚起见,它们将成为初始模型的一部分]