如何将Javascript类转换为ScalaJS

问题描述

我有这个简单的Javascript代码

import Modeler from 'bpmn-js/lib/Modeler';

import diagramXML from './diagram.bpmn';

const modeler = new Modeler({
  container: '#canvas'
});

modeler.importXML(diagramXML);

在浏览器中打开时会显示一个图。

我想在 ScalaJS 中执行此操作,但是我错过了一些事情。

这是我的代码

@JSImport("resources/diagram.bpmn",JSImport.Default)
@js.native
object DiagramXML extends js.Object

object Main {

  @JSExportTopLevel("main")
  def main(): Unit = {
    val modeler = new Modeler(js.Object(
      "container" -> "#canvas"
    ))

   modeler.importXML(DiagramXML.toString)
 }
}

这是我Modeler的门面:

@js.native
@JSImport("bpmn-js/lib/Modeler","Modeler")
class Bpmnjs(options: js.Object) extends js.Object {

  def importXML(xml: String): js.Promise[Any] = js.native

}

当我调试时,xml已正确加载。唯一缺少的是它已在DOM中正确呈现。

解决方法

我可以在您的翻译中找出两个问题。第一个是import中的bpmn-js。 JS导入为

import Modeler from 'bpmn-js/lib/Modeler';

应翻译为

@JSImport("bpmn-js/lib/Modeler",JSImport.Default)

根据the documentation on translating import into @JSImport

另一个问题更加微妙。在调用new Modeler时,您已经

js.Object(
  "container" -> "#canvas"
)

(可能很不幸)可以编译,但没有执行您认为的操作。它会创建两个字符串的Scala元组,然后将其传递给JavaScript函数Object(...),该函数实际上将按原样返回它(因为Scala元组已经是一个对象)。

您想要的是一个带有字段container的JavaScript对象,您可以将其编写为

new js.Object {
  val container = "#canvas"
}

一种更好的方法是使选项对象在外观中静态键入:

class BpmnJS(options: BpmnJSOptions) extends js.Object {
  ..
}

trait BpmnJSOptions extends js.Object {
  var container: js.UndefOr[String] = js.undefined
}

这样,您可以将其命名为

new BpmnJS(new BpmnJSOptions {
  container = "#canvas"
})