我希望能够从 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
放入控制台时,它确实返回了该函数 - 因此它似乎正在加载连接器,但无法找到要调用的实际方法。好奇我还缺少什么。如有任何建议,将不胜感激。
首先,必须“不要在新代码中使用 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
实例。