GWT JSNI - JavaScriptException TypeError - 方法不是函数

问题描述 投票:0回答:1

我希望能够从 Javascript 中的

StartView
事件调用在我的
onclick
类中声明的方法。我正在遵循官方 GWT 文档,但在控制台中仍然收到
JavaScriptException TypeError - doThing is not a function
错误。我已经在这里查看了其他类似的问题,但到目前为止尚未找到解决方案。我尝试在 JSNI 和 JSInterop 中实现一个解决方案 - 下面是我已经克服 GWT 编译错误的最远的解决方案。

StartView.java - 当

StartView.loadJS()
初始化时,我调用
StartView

    public void doThing() {
        System.out.println("do thing");
    }

    public static native void loadJS() /*-{
        var that = this;
        $wnd.doThing = $entry(function() {
            [email protected]::doThing()();
        });
    }-*/;

start.js(外部js文件,通过ScriptInjector注入StartView。其他方法使用JSInterop)

...
// Inside of my onclick handler
 window.doThing();

当我单击该元素时,我在控制台中收到以下错误:

Exception: com.google.gwt.core.client.JavaScriptException: (TypeError) : that_0_g$.doThing_0_g$ is not a function 

当我将

window.doThing
放入控制台时,它确实返回了该函数 - 因此它似乎正在加载连接器,但无法找到要调用的实际方法。好奇我还缺少什么。如有任何建议,将不胜感激。

javascript java gwt jsni
1个回答
0
投票

首先,必须“不要在新代码中使用 JSNI”——除非您的项目依赖于古老的 GWT 构建,否则这在 JsInterop 中会更容易。首先,定义(或重用)一个

@JsFunction
接口,该接口描述 JS 调用 Java 的契约,创建一个可以将其分配给的全局字段,然后在 vanilla java 中导出实例方法:

/** Like Runnable, but no default methods, and has {@link JsFunction}. */
@JsFunction
public interface JsRunnable {
  void run(); // your example has no params and no return type, so this fits
}

public static void loadJS() {
  JsRunnable lambda = this::doThing; // bug is clear in java!

  // Assign as a new property on window
  Js.asPropertyMap(DomGlobal.window).set("doThing", lambda);
}

public void doThing() {
  System.out.println("do thing");
}

请注意,loadJS 的翻译清楚地表明了为什么你的 JSNI 不起作用(稍后会详细介绍) - 如果你尝试使用

this
,Java 会抱怨,因为
loadJS()
是静态的并且没有
this
!但是,您从构造函数内部调用
loadJS()
,您可以将实例作为参数传递,或者使
loadJS()
非静态。


从你的问题

    public static native void loadJS() /*-{
        var that = this; // Where should "this" come from?
        $wnd.doThing = $entry(function() {
            [email protected]::doThing()();
        });
    }-*/;

由于这是一个

static
方法,所以没有
this
(好吧,在 JS 中,is
this
,但它不是
StartView
,它完全是另一回事)。由于
doThing
是一种非
static
方法,因此没有明确的方法来说明您想要调用
StartView
的哪个
doThing()
实例。

最简单的答案是从该方法中删除

static
,以便按照您的预期正确捕获
this
。另一种选择可能是将
StartView
实例传递给
loadJS
并在该实例上调用 doThing。

你得到的错误几乎肯定是

this
结果是
window
,并且
@package.StartView::doThing()
引用代表了一些在窗口上不存在的混淆方法名称,这是有道理的,因为你想要
this 
成为
StartView
实例。

© www.soinside.com 2019 - 2024. All rights reserved.