我的 UiBinder 模板中有一个 ID 为“test”的 div,并且想要在其上执行一些 jQuery 内容。如果我在 UiBinder java 类末尾执行 native 方法,则 javascript 调用会失败,因为 div 似乎还不存在:
public MyWidget() {
initWidget(uiBinder.createAndBindUi(this));
AppUtils.initializeSomething();
}
解决方法是使用计时器并稍微延迟我的 JS 代码。这可行,但在我看来相当丑陋。如果 UiBinder 模板完全加载,是否有任何干净的解决方案来执行我的 javascript?
public MyWidget() {
initWidget(uiBinder.createAndBindUi(this));
new Timer(){
@Override
public void run() {
AppUtils.initializeSomething();
};
}.schedule(1000);
}
native 方法:
public static native void initializeSomething()/*-{
$wnd.$('#test').doSomeJsStuff();
}-*/;
最佳答案
public MyWidget() { initWidget(uiBinder.createAndBindUi(this)); AppUtils.initializeSomething(); }
由于这只是构造函数,此时 DOM 元素都存在,但尚未附加,因此任何尝试查找附加 dom 元素的代码都将失败(例如,jQuery 将尝试执行 document.getElementById
来计算 $('#test')
,这将失败,因为小部件尚未附加到文档。
相反,您有两个基本选择:
- 立即运行初始化,但实际上传入 dom 元素,而不是尝试查找它(并失败),或者
- 等到 dom 元素实际附加后再尝试初始化。
运行初始化只需知道要修改哪个元素即可。由于您使用的是 uiBinder,因此您可以在 Java 类中创建一个 Element
字段,并要求将其分配给某个设置了 ui:field
属性的元素同名。这就像您当前将元素的 ID 设置为“test”,然后期望使用 `$('#test') 找到它。像这样的事情:
在您的 .ui.xml 文件中:
<g:HTMLPanel>
<div ui:field="testElement">...</div>
...
</g:HTMLPanel>
在您的 .java 类中:
@UiField Element testElement;
然后在 JSNI 方法中,您可以传入元素或在调用它时引用它。您的 initializeSomething
和构造函数可能如下所示:
public MyWidget() {
initWidget(uiBinder.createAndBindUi(this));
AppUtils.initializeSomething(this.testElement);
}
public static native void initializeSomething(Element elt)/*-{
//jQuery lets you wrap a dom element instead of finding it,
//and we already know where it is
$wnd.$(elt).doSomeJsStuff();
}-*/;
<小时/>
接下来,等待附加到 DOM 来运行 doSomeJsStuff()
- 两种简单的方法。在原始 JS 中,您可以使用第一种方法,尽管我认为这对于 JS 来说是非常错误的。所以这是第一种错误的方法:
//make the elements
MyWidget widget = new MyWidget();
//attach them to the dom (note that if you attach to a different
// parent, that parent too must be attached
// and so on).
RootPanel.get().add(widget);
//now that we are attached, run the setup code!
widget.doSomeJsStuff();
这显然很愚蠢 - 我们正在编写一个类,该类应该足够聪明,能够照顾自己!
让我们再试一次,这次指示类在附加后运行 doSomeJsStuff()
。有两种方法可以完成这项工作,onAttach
和 onLoad
- 没有关于 doSomeJsStuff
做什么的具体细节,我不知道什么您需要,但 onLoad
更容易使用。
值得注意的是,每次附加小部件时都会调用这些方法,而不仅仅是第一次。如果这对您很重要,您可能需要检查该小部件是否尚未附加。如果没有,我们需要的是:
@Override
protected void onLoad() {
doSomeJsStuff();
}
关于javascript - GWT UiBinder - 渲染模板后执行 JS?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31010704/