Mar*_*son 3 f# fable-f# elmish
我创建了一个应用,可以下载一些数据并使用Google图表将其绘制到div具有特定的Id。
在静态页面上可以正常工作。但是,当使用菜单在多个视图之间切换时,当切换回适当的视图时,我很难重新绘制图表。
如果在更新模型时使用命令重绘图表,则该请求将失败,因为div尚未呈现该特定视图。
完成View阶段后,Model-View-Update有没有办法触发命令?还是重绘图表的更好方法?
后面是示例代码(不可运行,但应易于理解)。单击“获取数据”按钮可以正常工作,但是如果您随后又切换到另一页,我将找不到重新绘制图表的方法。
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
Run Code Online (Sandbox Code Playgroud)
HTML只是:
<!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>
Run Code Online (Sandbox Code Playgroud)
您可以通过使用Ref属性来检测何时安装了无状态的React元素。
例如,这是我在生产应用程序中使用的:
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
)
]
[ ]
Run Code Online (Sandbox Code Playgroud)
另一种方法是将转换div [ Id "Chart1" ] [ ]为有状态的React组件,componentDidMount并在调用时触发绘制。
| 归档时间: |
|
| 查看次数: |
495 次 |
| 最近记录: |