DOMContentLoaded事件针对单个页面加载触发两次

时间:2010-12-04 19:22:31

标签: javascript dom event-handling firefox-addon

几个月前我创作了一个最近失败的Firefox附加组件。附加组件基本上查找特定的URL,然后修改页面的DOM。我追踪到了#AV;安全搜索"(意外)安装的失败。添加在。我发现,在禁用AVG插件的情况下,DOMContentLoaded事件会为文档触发一次(我最初预期的行为),但启用它后,DOMContentLoaded事件会为文档触发两次。我的加载项将一个列插入到HTML表中,因此事件会触发两次,所以会插入两个重复的列而不是一个。

这是我附加组件的精简初始化代码:

var hLoadListener = function(event) { myAddon.initialize(event); }
var hContentLoadedListener = function(event) { myAddon.onContentLoaded(event); }

myAddon.initialize = function(aEvent)
{
    gBrowser.addEventListener("DOMContentLoaded", hContentLoadedListener, false);
};

myAddon.onContentLoaded = function(aEvent)
{
    if (!(aEvent.originalTarget.nodeName === "#document")) { return; }

    var doc = aEvent.target; // document that triggered "onload" event

    if (!(doc instanceof HTMLDocument)) { return; }
    if (!doc.location) { return; }

    var href = doc.location.href; // URL of current page

    if (URLRegExp.test(href))
    {
      // Modify the page's DOM
    }
};

window.addEventListener("load", hLoadListener, false);

这个问题似乎很容易通过插入一个独特的DOM元素然后在开始时测试它的存在来解决。我的问题是附加开发人员是否应该期望此事件行为正常或者此问题主要是AVG插件中的错误/副作用?

3 个答案:

答案 0 :(得分:3)

我不知道我是否会认为这是“正常”,但外部应用程序影响插件操作的可能性是无穷无尽的。

也就是说,我认为无论AVG导致这种异常,如你所说,聪明的做法是在插入之前检查列是否存在,因为AVG可能不是影响firefox事件触发器的唯一外部应用程序

我非常厌倦DOM驱动的事件,因为在我自己的插件中,并且在整个开发过程中对它的测试显示了基于如此多变量(不同操作系统,不同版本的FF,主机上不同应用程序,任何给定用户FF等内的不同插件。)

  

总结:

     
      
  • AVG中的错误?也许。
  •   
  • 您的插件效果是否有可能受到其他许多来源的影响?绝对正确!
  •   
  • 解决方案:恕我直言 - 始终检查您的更改是否已完成   在对所有DOM项目进行实际更改之前,为了安全起见。
  •   

答案 1 :(得分:1)

尝试读取jquery的bindReady方法:

https://github.com/jquery/jquery/blob/master/src/core.js

你会发现:

if ( readyBound ) {
 return;
}
readyBound = true;

// Use the handy event callback
document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
// A fallback to window.onload, that will always work
window.addEventListener( "load", jQuery.ready, false );

答案 2 :(得分:0)

我这样做的原因是有一点利基,但如果对任何人有帮助的话,还会增加。

我正在运行VueJS,它不喜欢在应用程序中间嵌入<style><script>标签。因此,我有一个脚本,可以在Vue遇到它们之前找到它们并将其移动到<head>中。

当然,事件侦听器的移动导致将其重新添加到DOM后进行第二次设置。

我的问题的解决方案

  • id="some-id"添加到脚本
  • DOMContentLoaded事件监听器之后 注册地址:
  • document.getElementById('some-id').outerHTML = '';

这使Vue感到高兴,并允许在应用程序中包含脚本。