GWT-JSNI 在外部 JS 库中传递 JavaScriptObject
GWT-JSNI passing a JavaScriptObject in an external JS library
我拼命地尝试在 JSNI 方法中创建一个 Anno 对象,但我遇到了一个奇怪的问题:jsni 方法中的代码不起作用,但如果我在浏览器控制台中执行相同的操作, 它工作正常。
Java部分
我正在使用 JSONArray
,我添加了一些 JSONObject
(根据 Anno 文档,包含所有元素)。这是我的 JSNI 方法:
// I'm using the getJavaScriptObject() on my JSONArray
private static native void launch( JavaScriptObject steps )/*-{
var anno = new $wnd.Anno(steps);
anno.chainIndex().show();
}-*/;
浏览器部分
需要说明的是,该方法是在 onShow
事件上调用的,因此所有资源都已加载并呈现。因此,当显示元素并调用函数时,我的控制台出现此错误:
Couldn't find Anno.target 'h1'. --- anno.js:265
注意:在Anno.js中,h1是target的默认值。
但我的步骤值是正确的,当我在控制台中执行相同的命令时它起作用了:
var testAnno = new Anno([{
content: "namespinnerFrequencyA",
position: "center-right",
target: ".dataAuto0"
},{
content: "chooseFrequencyB",
position: "top",
target: ".dataAuto1"}]);
testAnno.show();
我不明白为什么它在一种情况下有效而在另一种情况下无效。我也尝试过使用 JSON.stringify
然后 JSON.parse
但它也不起作用。
编辑:
我想通了。在调试 anno.js 时我想到了一些事情:当我在控制台中初始化 Anno 时,本地范围看起来像这样(大图 here ):
但是当我使用 jsni 方法时,局部作用域完全不同,我的参数存储为实际数组而不是正常处理(大图 here ):
在我看来,错误消息是说找不到目标 dom 元素,而不是找不到目标 属性。当您的代码被触发时,该元素是否存在?确保它是并回复我。
问题在于 GWT 代码在 iframe 中运行(对于 sandboxing/isolation),而 Anno 仅支持来自 same 浏览上下文的数组类型。
有关问题的描述,请参阅 http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/ and http://web.mit.edu/jwalden/www/isArray.html。
ECMAScript 5.1 添加了一个 Array.isArray()
函数来解决该问题并具有广泛的浏览器支持(支持 IE9):https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
jQuery 也有一个,这让(我)无法理解 Anno 不使用它而不是使用损坏的 if arg.__proto__ is Array.prototype
(除非它是设计使然)。所以首先要做的事情是:在 Anno 上提交问题。
作为解决方法,应该可以使用 $wnd.Array.apply($wnd.Array, steps)
将数组从顶部复制到数组 window。
我拼命地尝试在 JSNI 方法中创建一个 Anno 对象,但我遇到了一个奇怪的问题:jsni 方法中的代码不起作用,但如果我在浏览器控制台中执行相同的操作, 它工作正常。
Java部分
我正在使用 JSONArray
,我添加了一些 JSONObject
(根据 Anno 文档,包含所有元素)。这是我的 JSNI 方法:
// I'm using the getJavaScriptObject() on my JSONArray
private static native void launch( JavaScriptObject steps )/*-{
var anno = new $wnd.Anno(steps);
anno.chainIndex().show();
}-*/;
浏览器部分
需要说明的是,该方法是在 onShow
事件上调用的,因此所有资源都已加载并呈现。因此,当显示元素并调用函数时,我的控制台出现此错误:
Couldn't find Anno.target 'h1'. --- anno.js:265
注意:在Anno.js中,h1是target的默认值。
但我的步骤值是正确的,当我在控制台中执行相同的命令时它起作用了:
var testAnno = new Anno([{
content: "namespinnerFrequencyA",
position: "center-right",
target: ".dataAuto0"
},{
content: "chooseFrequencyB",
position: "top",
target: ".dataAuto1"}]);
testAnno.show();
我不明白为什么它在一种情况下有效而在另一种情况下无效。我也尝试过使用 JSON.stringify
然后 JSON.parse
但它也不起作用。
编辑:
我想通了。在调试 anno.js 时我想到了一些事情:当我在控制台中初始化 Anno 时,本地范围看起来像这样(大图 here ):
但是当我使用 jsni 方法时,局部作用域完全不同,我的参数存储为实际数组而不是正常处理(大图 here ):
在我看来,错误消息是说找不到目标 dom 元素,而不是找不到目标 属性。当您的代码被触发时,该元素是否存在?确保它是并回复我。
问题在于 GWT 代码在 iframe 中运行(对于 sandboxing/isolation),而 Anno 仅支持来自 same 浏览上下文的数组类型。
有关问题的描述,请参阅 http://perfectionkills.com/instanceof-considered-harmful-or-how-to-write-a-robust-isarray/ and http://web.mit.edu/jwalden/www/isArray.html。
ECMAScript 5.1 添加了一个 Array.isArray()
函数来解决该问题并具有广泛的浏览器支持(支持 IE9):https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
jQuery 也有一个,这让(我)无法理解 Anno 不使用它而不是使用损坏的 if arg.__proto__ is Array.prototype
(除非它是设计使然)。所以首先要做的事情是:在 Anno 上提交问题。
作为解决方法,应该可以使用 $wnd.Array.apply($wnd.Array, steps)
将数组从顶部复制到数组 window。