无法从 F# 中的 vis 节点模块调用函数网络

Unable to call function Network from vis node module in F#

我在我的 Fable-F# 项目中使用 vis.js 依赖项,并希望调用网络函数以可视化显示网络。如何将 JSON 数据从 F# 传递到网络函数?

导入模块的F#代码

open Fable.Import.React
open Fable.Helpers
open Fable.Helpers.React
open Fable.Helpers.React.Props
open Fable.Core
open Fable.Core.JsInterop
open Fable.Import
open Fable.Import.Browser

    [<Import("default", "vis")>]
    let Network (we: React.event)  = jsNative
    let destination = Browser.document.getElementById "app"
    let response = Network destination  JsonData options

Vis.js节点模块代码,带三个参数Github

  function Network(container, data, options) {
  if (!(this instanceof Network)) {
    throw new SyntaxError('Constructor must be called with the new operator');
  }

  // set constant values
  this.options = {};
  this.defaultOptions = {
    locale: 'en',
    locales: locales,
    clickToUse: false

图表使用JS和HTMLGithub供参考

要使用 vis 库,您可以按照以下步骤操作:

  1. 转到 @types/vis npm 包
  2. 跟随link并复制index.d.ts文件的内容
  3. 粘贴到ts2fable online
  4. 的左侧面板
  5. 然后您可以将生成的定义文件复制并保存到您的项目中(vis.fs 中的示例)。您将有(在撰写此答案时)4 个错误。您可以评论相应的行。

对我来说:

// At the top of the file
type MomentInput = Moment.MomentInput
type MomentFormatSpecification = Moment.MomentFormatSpecification
type Moment = Moment.Moment

// In the middle of it
type [<AllowNullLiteral>] TimelineStatic =
    interface end
  1. 现在您可以使用 vis.js

这里移植了简单的网络代码:

// Fable demo ported from http://visjs.org/examples/network/basicUsage.html
module Client

open Fable.Core
open Fable.Core.JsInterop
open Fable.Import

// We import the vis.css style
importSideEffects "vis/dist/vis.css"

// We create an access to the vis library
// We could put it under vis.fs file but it's easier to access it from here
[<Import("*", "vis")>]
let visLib : vis.IExports = jsNative

// Helper to make the code easier to read
let createNode id label =
    jsOptions<vis.Node>(fun o ->
        o.id <- Some !^id
        o.label <- Some label
    )

// Helper to make the code easier to read
let createEdge from ``to`` =
    jsOptions<vis.Edge>(fun o ->
        o.from <- Some !^from
        o.``to`` <- Some !^``to``
    )

// If I was using this library I would probably write some helpers to have something like:
// Node.empty
// |> Node.withId 1
// |> Node.withLabel "My label"
// |> ...
// Like that the code is cleaner and more flexible

// From here this is almost a 1 to 1 with the JavaScript code
let nodes =
    ResizeArray([|
        createNode 1. "Node 1"
        createNode 2. "Node 2"
        createNode 3. "Node 3"
        createNode 4. "Node 4"
        createNode 5. "Node 5"
    |])
    |> visLib.DataSet.Create

let edges =
    ResizeArray([|
        createEdge 1. 3.
        createEdge 1. 2.
        createEdge 2. 4.
        createEdge 2. 5.
        createEdge 3. 3.
    |])
    |> visLib.DataSet.Create

let datas =
    jsOptions<vis.Data>(fun o ->
        o.nodes <- Some (U2.Case2 nodes)
        o.edges <- Some (U2.Case2 edges)
    )

let container = Browser.document.getElementById("elmish-app");

// Because we don't have any option to pass, we need to give an empty object 
// otherwise vis.js failed at runtime
let network = visLib.Network.Create(container, datas, createEmpty)