2012-08-24 91 views
3

我試圖將大部分原生JavaScript代碼從JSNI方法中移出並轉換爲腳本,並且只是利用本地JSNI方法來調用這些外部方法。GWT:可以從外部JavaScript代替JSNI調用Java方法嗎?

現在我遇到了一個點擊處理程序的問題。當用戶點擊某個元素時,JSNI方法會執行一些基於JQuery的動畫,然後在回調中調用Java方法。一個簡單的例子是:

public native void attachClickHandler(SomeCustomPanel customPanel) /*-{ 
    $wnd.jQuery("#theElement").click(function() { 
     // some JQuery animation logic here... 
     $wnd.jQuery("#theElement").animate({ top: "500px" }, 500, function() { 
      [email protected]::doSomething()(); 
     }); 
     // some other code here... 
    }); 
}-*/; 

此代碼的工作原理。它按預期進行編譯和工作。我想將其移入外部JavaScript中。我嘗試了以下。我把這個在外部JavaScript:

function attachClickAction(customPanel) { 
    $("#theElement").click(function() { 
     // other stuff... 
     $("#theElement").animate({ top: "500px" }, 500, function() { 
      [email protected]::doSomething()(); 
     }); 
     // other stuff... 
    }); 
} 

而修改這樣的原生功能:

public native void attachClickHandler(SomeCustomPanel customPanel) /*-{ 
    $wnd.attachClickAction(customPanel); 
}-*/; 

但不正確。 JavaScript文件甚至不會加載,因爲這是不正確的JavaScript。 (丁目的開發工具給我的錯誤消息「未捕獲的SyntaxError:意外的標識符」。)

有沒有辦法來調用外部JavaScript文件, Java方法從JSNI方法?

我在GWT 2.4中,如果它很重要。

回答

5

答案是不,您不能從外部JavaScript函數明確調用Java方法。

但是,您可以很聰明並利用JavaScript允許您將函數本身作爲參數傳遞的事實。

我修改了我的JavaScript函數,像這樣:

function attachClickAction(callbackFunction) { 
    $("#theElement").click(function() { 
     // other stuff... 
     $("#theElement").animate({ top: "500px" }, 500, callbackFunction); 
    // other stuff... 
    }); 
} 

而且在我的Java代碼中,我明確地通過Java方法作爲回調函數參數:

public native void attachClickHandler(SomeCustomPanel customPanel) /*-{ 
    $wnd.attachClickAction(function() { 
     [email protected]::doSomething()(); 
    }); 
}-*/; 

這樣,JSNI方法時編譯時,它會正確調用doSomething() Java方法,並且該方法調用會完全傳遞到外部JavaScript函數。

+2

注意:您應該使用'$ entry()'調用'customPanel ... doSomething()()'。 –

+0

@avasopht - 爲什麼?我從來沒有見過這樣的構造。你可以解釋嗎? –

+3

它圍繞某些try/catch語句進行調用,以避免GWT/javascript中的Java代碼異常將達到純JavaScript代碼空間。 –

4

雖然您不能直接從JavaScript與香草GWT調用Java classe的方法,但是 gwt-exporter執行了很多從原生JavaScript調用「Java」對象方法所需的工具。

你可以做這樣的事情:

的Java:

@ExportPackage("") 
@Export("MYOBJ"); 
class MyClass implements Exportable { 
    public void doSomething(); 
} 

的JavaScript:

MYOBJ.doSomething(); 

GWT-出口與GWT 2.4效果很好,

+0

不幸的是,我無法添加外部依賴項,但是您提出了建議。 –

2

是的,你可以導出您的Java(GWT)方法作爲JavaScript函數,您可以將Java對象放入JavaScript變量中。這裏有一個簡單的例子:

@Override 
public void onModuleLoad() { 
    exportJavaMethodsToJs(); 

    final SomeCustomPanel firstCustomPanel = new SomeCustomPanel("first"); 
    exportJavaObjectToJs("firstCustomPanel", firstCustomPanel); 

    final SomeCustomPanel anotherCustomPanel = new SomeCustomPanel("another"); 
    exportJavaObjectToJs("anotherCustomPanel", anotherCustomPanel); 
} 

native void exportJavaMethodsToJs() /*-{ 
    $wnd.doSomething = function(panel) { 
    [email protected]::doSomething()(); 
    } 
    // Export any methods you need in JavaScript here... 
}-*/; 

native void exportJavaObjectToJs(final String key, final Object object) /*-{ 
    $wnd[key] = object; 
}-*/; 

然後,在JavaScript(!onModuleLoad()被調用後),您可以輕鬆地使用它像

doSomething(firstCustomPanel); 
doSomething(anotherCustomPanel); 

你的榜樣,現在應該是這樣的:

jQuery("#theElement").click(function() { 
    // some JQuery animation logic here... 
    $wnd.jQuery("#theElement").animate({ top: "500px" }, 500, function() { 
     doSomething(firstCustomPanel); 
    }); 
    // some other code here... 
});