【问题标题】:JavaScript - dynamic SVG - onload attribute - event not triggeredJavaScript - 动态 SVG - onload 属性 - 未触发事件
【发布时间】:2016-09-13 23:37:20
【问题描述】:

将动态 SVG 内容插入 DOM 无法按预期工作,具有 SVG 元素 onload 属性(包含 JavaScript)关于:“setInterval()”。

如该问题的搜索标签中所述;这是普通的(valilla)JavaScript(不是 jQuery);以下是问题的细分:

  • 我有一些 SVG 代码(纯文本)作为 innerHTML 插入到 <div>
  • SVG 元素有一个 onload 属性,其中包含一些 JavaScript
  • JavaScript 包含 setInterval(...) -(根本不起作用)
  • 我从临时 div 中获取 SVG 元素并将其作为函数的结果返回。
  • 此结果被附加到活动 DOM(正文)中的某个元素中

奇怪的问题:

  • onload 属性中的任何其他代码都可以正常工作,
  • 只有setInterval & setTimeout 被完全忽略

更多信息:

在运行时(启动),SVG 代码从现有的embed 元素.getSVGDocument()(加载后)中获取,并准备为纯 HTML,可以用作模板来创建许多其他代码相同的源代码。我没有使用cloneNode(true) -因为:间隔用于动画(连续缓慢和平滑旋转) - 这可能会对客户端资源产生重大影响,因此,我认为最好获取代码并将其保留为模板 - 然后从 DOM 中删除原始代码。

考虑到以上所有,一切正常:

  • (新的)SVG 出现在屏幕上,一切都很好,像花花公子一样
  • 当我console.log 使用的(内联)SVG 代码时,一切看起来都很完美
  • 我没有收到任何错误,也没有可以消除错误的错误处理程序 (window.onerror == null)
  • SVG 节点的 onload 属性中的 JavaScript(文本)适用于:console.log(this) -(在日志中生成 SVG 元素) - 但是,如前所述:setInterval()setTimeout() 只是简单地忽略 - 没有任何错误和警告。

以下代码是一个非常简短的示例,并且(遗憾的是)它可以工作;但是,在我的生产应用程序中却没有。

代码:

var html = '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" onload="setInterval(function(){ console.log(\'testing\'); },500);">';
var temp = document.createElement('div');  temp.innerHTML = html;
var node = temp.getElementsByTagName('svg')[0];

document.body.appendChild(node);

如果你在一个新的js文件中测试上面的代码,它可以工作;但是,对于我的生活,我找不到它在我的应用程序中中断的原因;正如所解释的,这真的很简单。

问题:

有谁知道我不知道这方面是否存在一些“问题”?也许是名称间距?

如果需要源代码,我可以将其加载到 JSFiddle 或 CodePen - 如果需要,但是,它有很多代码和很多文件,可能不需要发布。

我确定这只是小事;例如,计时器如何根据范围注册,以及它在.bind() 中的影响?

我真的很坚持这个,我有点需要它来为求职面试留下好印象;因此,如果您知道任何可以提供帮助的信息,我将非常感谢您的意见。

谢谢。

【问题讨论】:

  • 如果您在 HTML 中使用 setInterval 声明该函数,并从 SVG 的 onload 中调用它,它是否有效?您是否尝试过多种浏览器,因为这可能是一个错误?
  • @Tibo :: 我不确定我是否理解,但是,返回新 SVG 对象的函数只是抓取“准备好的”SVG 代码(纯文本)-> 从中创建一个 DOM 节点(SVG) -> 并返回此节点。 JavaScript 代码(onload)应该保留在 SVG 文件中,因为它应该由另一个开发人员编辑,并且应该放在一起 - 在同一个地方。我已经用 Chrome、FireFox 和 Opera 对此进行了测试,所有 3 个都以完全相同的方式失败 - 没有错误 - 只是没有按预期工作,所以,它一定是我缺少的一些简单(和标准)的东西。
  • @Tibo 是的,它有效;在 Fx 和 Chrome 中尝试了这个简单的用例。在 Fx 中,您甚至不需要将节点附加到正文中。 data:text/html;charset=utf-8,&lt;!doctype html&gt;&lt;/body&gt;&lt;script&gt;var temp=document.createElement('div');%0Atemp.innerHTML='&lt;svg onload="console.log(\'onoad\');setInterval(function(){ console.log(\'interval\'); },500);"&gt;';var node = temp.getElementsByTagName('svg')[0];document.body.appendChild(node);&lt;/script&gt;
  • 伙计们,我刚刚发现了问题 - 并进行了修复;看,SVG 文件位于 &lt;embed&gt; 元素中,并且运行一次(在启动时),但被删除,因此同步代码有效。问题是:新元素的onload 事件没有被触发。所以,作为修复,我只是使用 onload JS 设置this 的属性,并在父文档(函数)中测试是否设置,如果没有 - 繁荣, - onload 没有触发新元素,所以我手动触发它。尽管如此,很高兴知道为什么onload 适用于@myf 上面的示例,但不适用于我的应用程序 - 因为它们几乎完全相同。
  • 也许如果有人可以发布有关“一般经验法则”的答案 - 或者可以为与此类事情相关的其他人解决此类问题的内容,我会很乐意投票并接受。

标签: javascript html svg setinterval onload


【解决方案1】:

嵌入内容、onload 属性和 DOM

以下可能对相关场景有所帮助:

  • 在定位异步源时,请确保 contentDocumentgetSVGDocument() 包含您需要访问的资源。 window.onloadDOMContentLoaded 事件与当前 DOM 相关,因此它可能有助于构建您自己的 listener->trigger 以实现跨浏览器解决方案,因为您需要的内容可能不会以同步方式准备好。

  • onload 属性/事件在插入非异步加载的动态内容时不会触发,但在某些情况下可能会触发,因此,再次自定义:
    听-> 触发器将解决这个问题。

具体问题

这个问题和上面第2点直接相关,答案真的很简单:

  • 在上述 SVG 的“onload”属性中,设置一个简单的值作为 this 的属性,例如:
    &lt;svg onload="this.ready = true; setTinterval(...)"
  • 在构造函数中,动态创建元素后,只需检查 svg-node 的 onload 事件是否被触发如下:
    if (!svgNode.ready){ svgNode.onload(); }

如果您的代码中有错误,但没有显示错误,请确保 window.onerrornull -或者如果它是一个函数,请确保它不返回 true -否则它可能会抑制错误,您将很难找出问题所在。

请随时改进此答案或发表评论,我会相应地改进它;但是,我们将不胜感激。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-25
    • 2014-05-05
    • 2017-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多