首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在寓言-elmish中,如何在视图呈现后触发命令?

在寓言-elmish中,如何在视图呈现后触发命令?
EN

Stack Overflow用户
提问于 2018-10-05 15:45:48
回答 2查看 1.3K关注 0票数 5

我创建了一个应用程序,它用Google下载一些数据并绘制成图,然后用一个特定的Id下载到一个Id

这在静态页面上工作得很好。但是,当使用菜单在多个视图之间切换时,当切换回适当的视图时,我很难重新绘制图表。

如果在更新模型时使用命令重新绘制图表,则请求会失败,因为尚未呈现特定的div

View阶段Model-View-Update已经完成时,是否有一种方法触发命令?还是重新绘制图表的更好方法?

下面的示例代码(不是可运行的,但应该是直接遵循的)。单击"Get data“按钮可以正常工作,但是如果您随后切换到另一个页面并返回,我将无法找到重新绘制图表的方法。

代码语言:javascript
复制
module Client

open Elmish
open Elmish.React

open Fable.Helpers.React
open Fable.Helpers.React.Props

open Fulma

type View = ShowChart | NoChart
type Model = { View: View; Values: float[] option }

type Msg =
    | RequestValues
    | ReceiveValues of float[]
    | PageWithChart
    | PageWithoutChart
    | DrawChart

let init () : Model * Cmd<Msg> =
    { View = ShowChart; Values = None }, []

let update (msg : Msg) (currentModel : Model) : Model * Cmd<Msg> =
    match msg with
    | RequestValues -> currentModel, Cmd.ofMsg (ReceiveValues [| 1.0; 3.0; 2.0 |])  // normally this would be a long-running process
    | ReceiveValues values -> { currentModel with Values = Some values }, Cmd.ofMsg DrawChart
    | DrawChart ->
        match currentModel.Values with
        | Some values ->
            let series = TheGamma.Series.series<_, _>.values values
            let chart = TheGamma.GoogleCharts.chart.line series
            TheGamma.GoogleCharts.chart.show chart "Chart1"
        | None -> ()
        currentModel, []
    | PageWithChart ->
        match currentModel.Values with
        | Some _ -> { currentModel with View = ShowChart }, Cmd.ofMsg DrawChart // FAILS as the div with Id="Chart1" does not exist yet
        | None -> { currentModel with View = ShowChart }, []
    | PageWithoutChart -> { currentModel with View = NoChart }, []

let button txt onClick =
    Button.button
        [ Button.OnClick onClick ]
        [ str txt ]

let view (model : Model) (dispatch : Msg -> unit) =
    match model.View with
    | NoChart ->
        div []
          [ div [] [ str "Page without chart" ]
            button "Show page with chart" (fun _ -> dispatch PageWithChart) ]
    | ShowChart ->
        div []
          [ div [] [ str "Page with chart" ]
            button "Get data" (fun _ -> dispatch RequestValues)
            button "Show page without chart" (fun _ -> dispatch PageWithoutChart )
            div [ Id "Chart1" ] [] ]

#if DEBUG
open Elmish.Debug
open Elmish.HMR
#endif

Program.mkProgram init update view
#if DEBUG
|> Program.withConsoleTrace
|> Program.withHMR
#endif
|> Program.withReact "elmish-app"
|> Program.run

HTML只是:

代码语言:javascript
复制
<!doctype html>
<html>
<head>
    <script type="text/javascript" src="http://www.google.com/jsapi"></script>
    <title>SAFE Template</title>
    <meta charset="utf-8">

    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.1/css/bulma.min.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" />
    <link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet">

    <link rel="shortcut icon" type="image/png" href="/Images/safe_favicon.png"/>
</head>
<body>
    <div id="elmish-app"></div>
    <script src="./js/bundle.js"></script>
</body>
</html>
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-10-06 15:40:00

您可以通过使用Ref属性来检测何时已挂载了无状态react元素。

例如,这就是我在生产应用程序中使用的:

代码语言:javascript
复制
div [ Id "Chart1"
      Ref (fun element ->
          // Ref is trigger with null once for stateless element so we need to wait for the second trigger
          if not (isNull element) then
              // The div has been mounted check if this is the first time
              if model.IsJustLoaded then
                  // This is the first time, we can trigger a draw
                  dispatch DrawChart 
          )
 ]
    [ ]

另一种方法是将div [ Id "Chart1" ] [ ]转换为有状态的react组件,并在调用componentDidMount时触发平局。

票数 8
EN

Stack Overflow用户

发布于 2018-10-05 22:48:31

在没有看到您的代码的情况下,给出具体的建议有点困难,但以下是如何处理它的一般想法。在您的情况下,我可能会使用从寓言Powerpack中承诺实现,并设置如下:

  • 图表绘制代码还没有绘制图表,它只是返回一个承诺,当解决后,将绘制图表。
  • 在视图函数中的div之后,立即使用这个黑客来触发一些Javascript代码,这些代码将解决这个承诺,触发draw()事件。(或者,如建议的对这个问题的另一个回答,将该代码放在视图底部的script元素中,这样它的执行就不会阻止任何其他的呈现,那么脚本内部就是解决这个问题的地方)。

对不起,这太模糊了;如果我看到了您的代码,我可能会提出更具体的建议。特别是,我不知道如何更好地处理传递这个承诺的问题:将它存储在模型中似乎是个坏主意(将一些可变的东西存储在不可变的数据模型中)。但是我还没有想出一个更好的主意。但是一些与承诺有关的东西似乎是处理这种情况的最好方法。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52669221

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档