GWT UiBinder - 渲染模板后执行JS?

时间:2015-06-23 18:29:41

标签: javascript java templates gwt

我的UiBinder模板中有一个ID为“test”的div,并希望在其上执行一些jQuery的东西。如果我在我的UiBinder java类的末尾执行本机方法,则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);

}

原生方法:

public static native void initializeSomething()/*-{

     $wnd.$('#test').doSomeJsStuff();
}-*/;

1 个答案:

答案 0 :(得分:1)

public MyWidget() {
    initWidget(uiBinder.createAndBindUi(this));
    AppUtils.initializeSomething();
}

由于这只是构造函数,此时DOM元素都存在,但尚未附加,因此任何尝试查找附加dom元素的代码都将失败(例如,jQuery将尝试{{1找出document.getElementById,由于小部件尚未附加到文档,因此会失败。

相反,您有两个基本选项:

  • 立即运行初始化,但实际传入dom元素而不是尝试找到它(并且失败),或者
  • 等到dom元素实际连接后再尝试初始化。

运行初始化只是已经知道要修改哪个元素。由于您使用的是uiBinder,因此可以在Java类中创建一个$('#test')字段,并要求将其分配给某个具有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()。有两种方法可以完成这项工作,onAttachonLoad - 没有关于doSomeJsStuff做什么的具体细节,我不知道你需要什么,但是{{1是一个更容易使用的人。

重要的是要注意,每次附加小部件时都会调用这些方法,而不仅仅是第一次。如果这对您很重要,您可能需要检查是否尚未附加小部件。如果没有,我们所需要的只是:

onLoad