在doc上执行写入:除非已明确打开,否则无法从异步加载的外部脚本写入文档。


67

我试图在页面加载执行后加载某个脚本,如下所示:

function downloadJSAtOnload(){
            var element = document.createElement("script");
            element.src = "scriptSrc";
            document.body.appendChild(element);
        }

         if (window.addEventListener)
                  window.addEventListener("load", downloadJSAtOnload, false);
            else if (window.attachEvent)
                  window.attachEvent("onload", downloadJSAtOnload);
            else window.onload = downloadJSAtOnload;

尽管此脚本似乎执行并下载了“ scriptSrc”,并将其附加在body标签末尾之前,但它在控制台(chrome)中产生以下消息(不是错误)

无法在“文档”上执行“写入”:无法通过异步加载的外部脚本写入文档,除非已明确打开该文档。

这到底是什么意思?我应该做些不同的事情吗?即使我得到了预期的行为?


2
这意味着您正在加载的脚本将执行document.write,当您通过<script>标签将其添加到页面时不支持该脚本。您可能应该查看脚本在做什么,并将脚本更改为不使用document.write
univerio 2014年

1
知道了,但是我无法更改该脚本。称之为官僚主义。我可以让脚本同步加载吗?不正确,因为它是在页面加载后发生的。
Parijat Kalia 2014年

是的,您可以与AJAX同步加载脚本内容,然后进行加载eval,尽管我不确定100%是否可行。
univerio 2014年

2
最近在github上找到了一个很棒的库,很好地解决了这个“限制”:github.com/krux/postscribe
Randy L

@univerio我也面临着同样的问题。document.write('\x3Cscript type="text/javascript" src="http://ads.appnexus.com/ttj?id=xyzpqr&cb=${CACHEBUSTER}">\x3C/script>');这是完美的工作,但是当我使用createElement('script')创建脚本时,我面临着同样的问题。你能在这里建议些什么吗?
RockStar '16

Answers:


86

在文档完全解析并关闭后,异步加载的脚本可能会运行。因此,您不能document.write()在这样的脚本中使用(从技术上讲可以,但是它不会做您想要的事情)。

您将需要document.write()通过创建DOM元素,然后使用.appendChild()or.insertBefore()或设置.innerHTML或某种直接DOM操作的机制将它们插入到特定的父级中,从而用显式DOM操作替换该脚本中的任何语句。

例如,代替内联脚本中的此类代码:

<div id="container">
<script>
document.write('<span style="color:red;">Hello</span>');
</script>
</div>

您可以使用它来替换上面的内联脚本,以动态加载脚本:

var container = document.getElementById("container");
var content = document.createElement("span");
content.style.color = "red";
content.innerHTML = "Hello";
container.appendChild(content);

或者,如果容器中没有需要附加的其他内容,则可以简单地执行以下操作:

var container = document.getElementById("container");
container.innerHTML = '<span style="color:red;">Hello</span>';

但是当我声明“ document.body.appendChild(element)”时,我是否没有做类似的事情?
Parijat Kalia 2014年

@ jfriend,Re“但是不会执行您想要的操作”,如果可以,该怎么办?如果需要,如何启用它?(这曾经在较旧的浏览器上起作用。)
Pacerier

2
@Pacerier-document.write()在文档加载完成后使用会导致当前文档被清除,然后写入新的空白文档。如果您想要这种行为,则只需在插入内容之前清除当前DOM。如果您有比这更详细的问题,请提出一个新问题,显示您的代码并描述所需的结果。
jfriend00

23

派对晚了一点,但是K​​rux为此创建了一个脚本,叫做Postscribe。我们能够使用它来解决此问题。


1
用我们的JavaScript库传递此库的最佳方法是什么?情况是我们给在该网站上运行的客户端JS标签。
RockStar '16

我不确定您在这里问什么@RockStar,但不是100%肯定,但是任何包含JS的常规方法都可以使用。您可以拉出cdnjs.com/libraries/postscribe并将代码复制/粘贴到现有的JS文件中,或者可以添加<script>标记指向该文件的cdnjs托管版本。可能是这种情况,您需要在其他脚本之前先加载它,因此,如果无法使其正常工作,则可能是原因。
兰迪·L

我们向网站所有者提供了JavaScript CDN链接,以使用该标记进行广告投放。我们无法要求每个所有者放置此postscribe.js,因此需要将其与我们的JS一起提供。
RockStar '16

postscribe似乎并没有在所有做任何事情,除非你明确的使用postscribe功能-非常令人失望
雷Nicholus

2

万一这对我遇到同样问题的任何人都是有用的。我通过jQuery将页脚引入网页。在页脚中有一些用于广告和重定向的Google脚本。我不得不将这些脚本从页脚移到页面上,然后直接放置在页面中,这消除了通知。


1
我遇到了同样的问题,但是脚本位于标签管理器创建的捆绑软件中。问题是由async属性引起的,唯一的解决方案是删除该属性,因为不允许我从标记管理器中移动脚本。
Giorgio Tempesta,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.