关于调试此类问题,您可以尝试以下操作:
.1。打开调试模式(参见 ref)
zk.xml
<zk>
<client-config>
<debug-js>true</debug-js>
</client-config>
<library-property>
<name>org.zkoss.web.classWebResource.cache</name>
<value>false</value>
</library-property>
</zk>
.2. 尝试重现此问题,这里我创建了一个示例,通过手动取消绑定组件来重现类似问题,如下所示(单击“测试”按钮查看类似错误)
测试.zul
<zk>
<textbox id="tbx" />
<button label="test">
<attribute name="onClick"><![CDATA[
String uuid = tbx.getUuid();
Clients.evalJavaScript("zk.Widget.$('$tbx').unbind();");
tbx.setValue("abc");
]]></attribute>
</button>
</zk>
.3. 查看 chrome 的开发人员工具中的错误消息,然后单击源链接:
.4. 左键单击 setAttr 下的第一行以添加断点。
.5. 刷新页面,再次点击“测试”按钮,我们可以看到右侧的“wgt”为空,wgt通常表示一个小部件(客户端的组件)。
.6. 现在我们知道一个widget变为null,然后ZK执行它的setAttr命令,为了调试它,我们可以简单地在调用bind_时记录每个uuid和className(bind_是widget生命周期的函数,基本上实例化了所有dom元素一个小部件)由客户端编程,并在单击按钮时再次记录所有小部件。
例如,
test.zul(更新)
<zk>
<script><![CDATA[
var allUuids = [];
zk.afterLoad("zul", function () {
var _wgt = {};
// override zk.Widget,
// basically zk.Widget is the
// root of all widget classes
zk.override(zk.Widget.prototype, _wgt, {
bind_: function (a, b, c) {
// call original function
_wgt.bind_.apply(this, arguments);
// each widget has a uuid and className
allUuids.push({uuid: this.uuid, ele: this.className});
}
});
});
function showAllUuids () {
var info,
wgt;
for (var i = 0; i < allUuids.length; i++) {
info = allUuids[i];
// get widget by uuid
wgt = zk.Widget.$('#'+info.uuid);
// show the old className and current status
// you can also try record some more information as needed
// e.g., parent, previousSibling, sclass, etc
zk.log(info.uuid + ' was ' + info.ele + ' now ' + (wgt? wgt.className : wgt));
}
}
]]></script>
<textbox id="tbx" />
<button label="test">
<attribute name="onClick"><![CDATA[
String uuid = tbx.getUuid();
Clients.evalJavaScript("zk.Widget.$('$tbx').unbind();");
tbx.setValue("abc");
Clients.evalJavaScript("showAllUuids();");
]]></attribute>
</button>
</zk>
.7. 现在我们将在单击“测试”按钮后收到下面带有更新的 zul 页面的日志消息,并让我们知道客户端的文本框小部件变为空,您还可以在 chrome 开发者工具网络中检查响应值。
希望这可以帮助
参考 :
ZK 客户端编程
打开调试模式
zk.Widget 中的 bind_