Javascript 如何使用qx.ui.embed.Html强制创建DOM元素?

Javascript 如何使用qx.ui.embed.Html强制创建DOM元素?,javascript,qooxdoo,Javascript,Qooxdoo,我正在尝试将一篇论文嵌入qooxdoo小部件。RaphaelJS是一个用于JavaScript的SVG绘图库,它需要在任何绘图之前绑定到HTML。 为此,我调用newqx.ui.embed.Html(“”)并将其添加到我的小部件中。之后,我应该通过将div ID传递给它来初始化Raphael 问题是在qx.ui.embed.Html()构造函数调用之后没有提交到DOM模型(即没有创建真正的DOM元素)。DOM元素的创建实际上是延迟的,直到小部件被绘制到屏幕上。我已经成功捕获了小部件的出现事件,之

我正在尝试将一篇论文嵌入qooxdoo小部件。RaphaelJS是一个用于JavaScript的SVG绘图库,它需要在任何绘图之前绑定到HTML
。 为此,我调用
newqx.ui.embed.Html(“
”)并将其添加到我的小部件中。之后,我应该通过将div ID传递给它来初始化Raphael

问题是
qx.ui.embed.Html()
构造函数调用之后没有提交到DOM模型(即没有创建真正的DOM元素)。DOM元素的创建实际上是延迟的,直到小部件被绘制到屏幕上。我已经成功捕获了小部件的
出现
事件,之后,元素的存在得到了保证,我可以初始化Raphael库并进行一些绘图


这种方法假设我必须从
事件处理程序中运行所有应用程序逻辑,这可能不是我想要的。有没有其他方法可以让小部件在主应用程序流中处于“准备好绘图”状态?

您可以做的是创建自己的小部件
RaphaelWidget.js

qx.Class.define("myApp.RaphaelWidget",
{
  extend : qx.ui.core.Widget,

  construct : function()
  {
    this.base(arguments);

    this.addListener("appear", this._onAppear, this);
  },

  members :
  {
    /**
     * Overwritten from qx.ui.core.Widget.
     */
    _createContentElement : function()
    {
      return new qx.html.Element("div", {
        overflowX: "hidden",
        overflowY: "hidden",
        border: "1px solid #aaa"  // just for debugging
      }, {"id": "canvas-raphael"});
    },

    _onAppear : function()
    {
      var paper = new Raphael(document.getElementById('canvas-raphael'), 250, 250);
      var circle = paper.circle(100, 100, 80);
    }
  }
});
var raphael = new myApp.RaphaelWidget();
raphael.setWidth(250);
raphael.setHeight(250);
this.getRoot().add(raphael);
然后在
应用程序.js中执行以下操作:

qx.Class.define("myApp.RaphaelWidget",
{
  extend : qx.ui.core.Widget,

  construct : function()
  {
    this.base(arguments);

    this.addListener("appear", this._onAppear, this);
  },

  members :
  {
    /**
     * Overwritten from qx.ui.core.Widget.
     */
    _createContentElement : function()
    {
      return new qx.html.Element("div", {
        overflowX: "hidden",
        overflowY: "hidden",
        border: "1px solid #aaa"  // just for debugging
      }, {"id": "canvas-raphael"});
    },

    _onAppear : function()
    {
      var paper = new Raphael(document.getElementById('canvas-raphael'), 250, 250);
      var circle = paper.circle(100, 100, 80);
    }
  }
});
var raphael = new myApp.RaphaelWidget();
raphael.setWidth(250);
raphael.setHeight(250);
this.getRoot().add(raphael);

现在,您可以在这个新的小部件类中开发特定于Raphael的代码。

强制渲染/DOM操作在qooxdoo中称为“刷新”。例如,Richard解决方案中的qx.html.Element有一个
.flush()
方法。您可能想试试这个,或者搜索术语“flush”

也就是说,冲洗是最后的手段,不应该过度使用,因为这会严重降低性能。在编写JavaScript时,不应该回避异步编程。甚至您的“main”方法也是回调,在某个时间点从qooxdoo运行时调用


有几个qooxdoo贡献集成了Rafael等第三方库。有关更惯用的解决方案,请参见(part.the
\uu addCanvas
方法),这是一个集成JS库的contrib。

Richard,感谢您的建议。代码比使用qx.ui.embed.Html时要简洁得多。不幸的是,它也有同样的问题:您不能在主应用程序流中使用这个小部件,就在它创建之后。想象一下,我们在拉斐尔Widget中有一个
foo
方法来绘制一些图形。如果在
this.getRoot().add(raphael)
之后调用
raphael.foo()
,这将不起作用,因为
canvas raphael
DOM元素当时还不存在。但是如果你做了
raphael.addListener(“出现”,function(){this.foo();})
,这就行了。我只是想知道是否有一种方法可以初始化小部件,使它在创建之后可以从主流中使用,而不是从某个事件处理程序中使用。