基本上,后端为我提供了drawio文件的内容(所以我们正在谈论xml模式),我需要在我们的webix页面中显示它。 到目前为止,我已尝试使用 iframe 来实现此目的,遵循 https://www.drawio.com/blog/embedding-walkthrough 的官方指南,但没有任何效果。如果我使用通常的
webix.$$().getIframe().postMessage
或 webix.$$().getWindow().postMessage
,消息就会通过(花了很多时间调试来查找drawio 有其对应侦听器的位置......它位于 app.min 的第 12369 行),但他们在那里检查:
L.source == (window.opener || window.parent)
这始终是错误的:
L
是活动
L.source
始终是window
window.opener
始终为空
window.parent
始终是主窗口(不是 iframe 的窗口)
不知道如何在父级中覆盖事件的源属性。我的意思是,这不应该自动成为调用窗口吗???
当使用 webix.$$().getIframe().contentWindow.postMessage 尝试整个操作时(如下面的代码所示),该消息甚至不会到达 iframe 内的drawio 代码...
无论如何,这是代码:
{
view: "iframe",
id: "iframe#1",
src: 'https://embed.diagrams.net/?embed=1', //&ui=atlas&spin=1&&libraries=1&modified=unsavedChanges&proto=json&chrome=0',
style: 'border:0;position:"fixed";top:0;left:0;right:0;bottom:0;width:100%;height:100%;cursor:default;'
}
这基本上应该给我一个 webix 中的 iframe - 具有所有推荐的样式 - 注释的 url 参数是我尝试过的,但他们似乎都无法解决它。在调试器中查看它,它至少看起来很像一个 iframe ...
const receive = (evt: MessageEvent<any>) => {
const frame = (webix.$$(this.getSubViewID("iframe")) as webix.ui.iframe).getIframe() as any;
//frame.setAttribute('frameborder', '0');
if (evt && frame.contentWindow && evt.source === frame.contentWindow) {
const msg = JSON.parse(evt.data);
if (msg.event === 'init') {
frame.contentWindow.postMessage(JSON.stringify({
action: 'load',
xml: this.xmlData,
autosave: 1
}));
}
if (msg.event === 'save' || msg.event === 'autosave') {
this.xmlData = msg.xml;
}
if (msg.event === 'exit') {
window.removeEventListener('message', receive);
frame.contentWindow.close();
}
}
};
window.addEventListener("message", receive);
无论我尝试什么,它总是跳转到 postMessage 部分,xml 是您在编辑器中打开 .drawio 文件时看到的 1:1 xml。它永远不会跳转到保存/自动保存中的断点。在 postMessage 断点之后,如果旋转器被激活,则旋转器将永远旋转,否则它只是在错误状态下保持为空,您甚至无法添加新内容(取决于所选的 ui,所有内容都显示为灰色,或者根本不显示任何内容)得到添加)。还尝试了我在 github 的某个地方提到的 embedInline URL 参数,但是那个参数使得整个事情根本无法加载。
非常感谢任何有关我可能做错的事情的指示。
显然,如上面的代码所示,在我无数次尝试使这项工作正常进行的过程中,目标原点的“*”丢失了。更糟糕的是,在调试时,Chrome 调试器显然弄乱了发送的事件(基本上用来自同一窗口的通用事件替换该事件,但没有数据)
经验教训:
请勿尝试使用 Chrome 调试器调试与 postMessage 的跨窗口通信。当您在远程代码中设置断点时,Chrome 就会搞乱所有事件。
仅供参考,正确的工作代码是:
const receive = (evt: MessageEvent<any>) => {
const frame = (webix.$$(this.getSubViewID("iframe")) as webix.ui.iframe).getIframe() as any;
frame.setAttribute('frameborder', '0');
if (evt && frame.contentWindow && evt.source === frame.contentWindow) {
const msg = JSON.parse(evt.data);
if (msg.event === 'init' && evt.origin === 'https://embed.diagrams.net') {
frame.contentWindow.postMessage(JSON.stringify({
action: 'load',
xml: this.xmlData,
autosave: 1
}), "https://embed.diagrams.net");
}
if (msg.event === 'save' || msg.event === 'autosave') {
this.xmlData = msg.xml;
}
if (msg.event === 'exit') {
window.removeEventListener('message', receive);
frame.contentWindow.close();
}
}
};
window.addEventListener("message", receive);