IE8 DOM不反映JS的变化

时间:2012-07-24 08:42:56

标签: javascript dom internet-explorer-8

我正在使用javascript对页面提供时已经存在的HTML元素进行一些简单的更改(例如更改div元素的背景图像,添加ID等)。这当然可以在除IE8之外的每个浏览器中正常工作,其中更改似乎没有反映在DOM中,所以当我在JS运行后解析dom时它无法找到我正在寻找的元素。该页面由标题中的2个javascript文件构成,1是外部第三方脚本,我无法控制但是添加了ID和背景图像的脚本。第二个是我的,在第一个之后被调用,并且正在解析文档,寻找具有新ID的特定元素。两者都是外部脚本,并且不在HTML源代码中内联。

我可以告诉它:

  • 竞争条件,2个外部Javascripts正在运行1正在更改按钮并添加id,另一个正在解析dom寻找特定元素,并且当它们同时运行时第二个永远不会找到元素
  • IE8在更改后没有正确刷新DOM

我的JS在头部的第一个JS之后被调用,因此您可以假设阻塞不会导致竞争条件,并且在我的JS运行之前元素将可用

我尝试过的事情:

  • 我尝试在我的代码运行之前向主体添加一个类以强制刷新DOM
  • 我使用过IE8开发人员工具,并且不存在ID和元素,但是如果我刷新几次就会神奇地出现(页面已经完全加载了,我可以完全与它进行交互)

有什么想法吗?

谢谢!

1 个答案:

答案 0 :(得分:1)

要记住的一件事是,当您创建多个<script>标记时,您无法保证它们加载的顺序,并且根据它们的构建方式 - 它们通常会尽快开始处理因为他们被装上了。

因此,如果要将一个本地文件和一个文件包含在CDN中,例如:

<script type="text/javascript" 
        src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js">
</script>
<script type="text/javascript" src="/js/my_script.js"></script>

您必须考虑到CDN文件的传送速度通常比托管文件快得多。在上面的例子中,这可能是一件好事 - 因为jQuery在您的脚本可能是理想之前加载到页面上 - 但是如果您要加载不同的第三方脚本,这可能依赖于某些元素存在于您的脚本负责创建的DOM,您的脚本可能无法及时创建它们。

想象一下这种情况:

<script type="text/javascript" src="https://someurl/somelib.js">
    // This script parses the DOM and applies alterations to certain items
</script>
<script type="text/javascript" src="/js/my_script.js">
    // This script creates the DOM elements the other script is supposed to alter
</script>

您的页面仅在本地文件/js/my_script.js首先加载时才有效 - 这不太可能,因为其他文件是从专用CDN提供的。

当两个文件都在本地提供时,情况更糟,例如:

<script type="text/javascript" src="/js/my_relied_upon_script.js"></script>
<script type="text/javascript" src="/js/my_reliant_script.js"></script>

在这种情况下,一切都取决于本地Web服务器如何处理HTTP请求,以确定以什么顺序发生的事情。

所以 - 解决方案:

1)让你的脚本等待document的{​​{1}}事件发生。因为只有在文档完全加载后才会发生此事件(包括完全加载其元素所需的任何其他HTTP请求,例如脚本,图像等) - 您可以保证脚本至少等到完整的DOM是加载。

2)使下级脚本等待触发事件。

使用jQuery,示例可能如下所示:

onready

现在 - 请记住,上面的转换是相当糟糕的,而不是你想要做的事情(例如内联CSS等等) - 但它们举了一个例子。由于// Script #1 $(document).bind('ready', function () { $('#NeedsBackground').css({ background: 'url(/gfx/bg.png)' }); var $wrapper = $('<div />').addClass('wrapper'); $('#NeedsWrapper').wrap($wrapper); // Here's the magic that enforces loading. $(document).trigger('Script1Finished'); }); // Script #2 $(document).bind('Script1Finished', function () { $('.wrapper').css({ border: '1px solid #000' }); }); 要求在运行之前存在Script #2元素,因此您需要确保它在.wrapper发生后发生。

在这种情况下,我们通过{{1}在文档上创建一个自定义事件来完成它,然后我们可以响应 - 并且我们只是在DOM被置于适当的状态后触发该事件