使用JS渲染DOM之前更改脚本src

时间:2019-03-11 08:26:48

标签: javascript jquery

所以我的网站上有这样的代码

<div class="bonus-button">
    <script language="javascript" type="text/javascript" src="https://somedomain.de/widget/button/PSIG2ng?skin=134&t_mc=kwk&btn=rec_company"></script>
</div>

我想做的是根据URL参数将t_mc=的值更改为kwk之外的另一个值。一个示例是www.somedomain.de/page?utm_source=email。当有人使用此参数进入一侧时,代码应如下所示:

<div class="bonus-button">
        <script language="javascript" type="text/javascript" src="https://somedomain.de/widget/button/PSIG2ng?skin=174&t_mc=email&btn=rec_company"></script>
    </div>

可以做到这一点,但是kwk仍然是传递的值,它不存在于源代码中,仅在chrome开发人员工具的elements选项卡中。

以某种方式,我认为我需要在一切真正存在之前就更早地进行更改……对吗?

if (window.location.search.indexOf('utm_source=') > -1) {
    function getParameterByName(name, url) {
    if (!url) url = window.location.href;
    name = name.replace(/[\[\]]/g, '\\$&');
    var regex = new RegExp('[?&]' + name + '(=([^&#]*)|&|#|$)'),
        results = regex.exec(url);
    if (!results) return null;
    if (!results[2]) return '';
    return decodeURIComponent(results[2].replace(/\+/g, ' '));
}

var kwksource = getParameterByName('utm_source');

var scriptsrc = document.querySelector('.bonus-button script').getAttribute('src');

var scriptsrcbottom = document.querySelector('.bonus-button-bottom script').getAttribute('src');

document.querySelector('.bonus-button script').setAttribute('src', scriptsrc.split('t_mc=kwk').join('t_mc=' + kwksource));
document.querySelector('.bonus-button-bottom script').setAttribute('src', scriptsrcbottom.split('t_mc=kwk').join('t_mc=' + kwksource));
} 
    <div class="bonus-button">
        <script language="javascript" type="text/javascript" src="https://t.tellja.eu/widget/button/PSIG2ng?skin=134&t_mc=kwk&btn=rec_company"></script>
    </div>

1 个答案:

答案 0 :(得分:1)

简短的回答:这是不可能的。

详细答案:

当浏览器正在阅读页面源代码并遇到<script>标记时,它将停止呈现页面负载并执行脚本并继续呈现。那是因为脚本可以使用document.write等各种方法来创建DOM节点。(defer属性可以改变这一点)

因此,如果要创建一个脚本,该脚本应该更改另一个脚本标记的URL,那么在加载和执行该脚本标记之前,该脚本必须在源代码中的该脚本标记之前出现。但是,在此脚本执行的这一刻,尚未对其进行解析,因此尚未成为DOM的一部分,因此完全可以访问。

反之,如果修改另一个脚本标签url的脚本紧随其后出现在源代码中,则说明先前的脚本已经加载并执行,因此修改为时已晚。

因此,更改给定脚本的源URL的唯一方法是在DOM中出现,如下所示:

[...document.querySelectorAll('script[src]')]
  .find(s => <some test to identify the script>)
  .setAttribute('src', 'the new value')

这将导致重新加载脚本。但这不会对DOM进行任何更改,删除任何事件监听器等,或者换句话说,不会做任何清理。

总而言之,唯一可靠的解决方案是在服务器端,这样脚本URL就从页面加载开始就正确。