【问题标题】:script tag only run the first time after inserted in the DOMscript 标签仅在插入 DOM 后第一次运行
【发布时间】:2011-06-09 13:51:04
【问题描述】:

很好奇为什么script标签插入dom后只运行一次。

script = document.createElement('script');
script.type = 'text/javascript'

script
//output: <script type=​"text/​javascript">​</script>​

document.body.appendChild(script);

script.innerHTML = 'console.log("Attempt one")'
//output Attempt one

script.innerHTML = 'console.log("Attempt two")'

script.innerHTML = 'console.log("Attempt three")'

//second and third attempts emit no output

有什么方法可以让脚本文本的其他更改运行?

我已经尝试将它包装到一个函数中,但没有成功...我找不到任何解释为什么 log 是第一次运行而不是后面的运行

【问题讨论】:

  • 你为什么不只是......执行这个功能?
  • @Dvir 我分享你的困惑。这是使用 javascript 的一种非常奇怪的方式。

标签: javascript html dom innerhtml


【解决方案1】:

只是在这里澄清一下,上面的代码可能是一个不好的方法,等等。 但问题实际上是指行为以及为什么会发生。

在过去的几分钟里玩过之后,我注意到,一旦每个脚本标签都附加到 DOM 并具有内容,javascript 只会为每个脚本标签运行一次。

因此,例如,您可以将script 标记附加到 DOM 中而没有任何内容... 那不会触发javascript。但是,一旦您使用 innerTextinnerHTML 等向该标签添加内容...它就会立即触发 javascript。

有趣的是,每个脚本标签似乎都处理一个 flag,每次为该特定标签运行 javascript 时,它都设置为 false,然后在发生这种情况后它不会不管为什么,再次开火。

这里也有一些有趣的测试:

正常行为

var script = document.createElement('script');

document.body.appendChild(script);

script.innerHTML = 'alert("attemp one")';
// outputs alert
script.innerHTML = 'alert("attemp two")';
// no output

深度克隆节点

var clone = script.cloneNode(true);
// <script>alert("attemp two")</script>

document.body.replaceChild(clone, script);
// no output

简单克隆节点

var clone = script.cloneNode();
// <script></script>

clone.innerHTML = 'alert("attemp two")';

document.body.replaceChild(clone, script);
// no output

更换新标签

var newScript = document.createElement('script');

newScript.innerHTML = 'alert("attempt three")';

document.body.replaceChild(newScript, script);
// output alert

如您所见,脚本标签将保留alreadyExecuted 属性,无论出于何种原因,如果您通过生成精确副本来克隆它...

这让我想到是否有任何方法可以将此标志设置为其原始初始值,而不是创建一个新的script 标记。

但在最坏的情况下,如果您真的需要使用它。创建一个将获得 script 的操作并不难,如果您有一些属性,则创建一个具有相同属性的新操作,然后用旧的但用新内容替换它。 javascript 会像第一次一样运行。

以下脚本可以很容易地被调用,它将用一个新的脚本标签替换旧的脚本标签,并通过简单地提供您希望替换内容的脚本标签来执行新的 javascript。

function innerScript(element) {

    var newElement = document.createElement('script'),
        attr;

    for (attr = 0; attr < element.attributes.length; attr += 1) {
        newElement.setAttribute(element.attributes[attr].name, element.attributes[attr].value);
    }

    element.parentNode.replaceChild(newElement, element);
    return newElement;

}

【讨论】:

    【解决方案2】:

    就是这样。您通常不必向现有标签添加新代码;要么创建一个新标签,要么更好地利用函数和事件。

    【讨论】:

      【解决方案3】:

      在脚本执行的任意点更改&lt;script /&gt; DOM 节点的内部文本不会触发整个脚本重新执行,不会。

      创建一个新的脚本标签,或者更好地改进您的方法。你永远不应该发现自己需要注入脚本标签;相反,只需以正常方式执行这些函数调用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-04-27
        • 2015-06-07
        • 2018-11-24
        • 2012-01-10
        • 1970-01-01
        • 1970-01-01
        • 2018-09-20
        相关资源
        最近更新 更多