Javascript GWT 中的模块函数与 JsInterop

Javascript module function in GWT with JsInterop

希望这比我做的更容易 - 我是一名 Java 编码员,一些内部 Java 脚本方面对我来说有点陌生。

尝试将出色的 CodeJar library 嵌入到 GWT 面板中。 CodeJar 有一个漂亮的 nice/simple 示例:

<script type="module">
  import {CodeJar} from './codejar.js'
  import {withLineNumbers} from './linenumbers.js';

  const editor = document.querySelector('.editor')

  const highlight = editor => {
    // highlight.js does not trim old tags,
    // let's do it by this hack.
    editor.textContent = editor.textContent
    hljs.highlightBlock(editor)
  }

  const jar = CodeJar(editor, withLineNumbers(highlight), {
    indentOn: /[(\[{]$/
  })

  jar.updateCode(localStorage.getItem('code'))
  jar.onUpdate(code => {
    localStorage.setItem('code', code)
  })
</script>

模块函数本身如下所示:

export function CodeJar(editor, highlight, opt = {}) { ... }

'editor'是一个Div引用,'highlight'是处理代码高亮的回调库函数。

我正在努力解决的问题是使 Javascript 模块与 GWT 一起工作的 JsInterop 标记和代码。上面有几个方面我正在努力解决

要加载脚本并使其可供 GWT 使用,您有(至少)3 种可能性:

  • <script type=module> 中使用静态 import,然后将 CodeJar 函数分配给 window 属性 以使其全局可用(即可能是另一个 global 对象而不是 window 实际上)
  • 使用来自 GWT 的动态 import(),使用 JsInterop 和可能的 elemental2-promise
  • 使用 Rollup/Webpack/whatever 将 CodeJar 模块转换为 non-module 脚本,这样您就可以以不同的方式使用它

接下来,您需要创建 JsInterop 绑定,以便您可以从 GWT 调用它;类似的东西(假设你让 CodeJar 在全球可用 window.CodeJar,并使用 elemental2-dom 作为 HTMLElement,但 com.google.gwt.dom.client.Element 也可以工作):

@JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "?")
interface CodeJar {
  @JsMethod(namespace = JsPackage.GLOBAL, name = "CodeJar")
  static native CodeJar newInstance(HTMLElement element, HighlightFn highlight);
  @JsMethod(namespace = JsPackage.GLOBAL, name = "CodeJar")
  static native CodeJar newInstance(HTMLElement element, HighlightFn highlight, Options opts);

  void updateOptions(Options options);
  void updateCode(String code);
  void onUpdate(UpdateFn cb);
  void destroy();
}

@JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "Object")
class Options {
  public String tab;
  public JsRegExp indentOn;
  public boolean spellcheck;
  public boolean addClosing;
}

@JsFunction
@FunctionalInterface
interface HighlightFn {
  void highlight(HTMLElement e);
}

@JsFunction
@FunctionalInterface
interface UpdateFn {
  void onUpdate(String code);
}

使用上面的代码,您应该能够使用类似以下内容创建编辑器:

CodeJar jar = CodeJar.newInstance(editor, MyHighlighter::highlight);

如果您使用动态 import(),请在表示从 promise 接收的模块的 @JsType 接口中用实例方法替换静态方法。