【问题标题】:Having the same widget on a page multiple time / variable clashes在页面上多次使用相同的小部件/变量冲突
【发布时间】:2016-06-07 02:14:52
【问题描述】:

我创建了一个 JavaScript/jQuery 小部件,它需要能够多次嵌入到页面中,每个页面都有不同的变量设置。目前,最后加载的小部件正在覆盖各种变量。

这里是一个精简版,用于示例目的。

(function () {

    var scriptName = "my.widget.js";
    var TGW;
    var jqueryPath = "https://ajax.googleapis.com/yada_yada..."; 
    var scriptTag;
    var jScript;

    /******** Get reference to self (scriptTag) *********/
    var allScripts = document.getElementsByTagName('script');
    var targetScripts = [];
    for (var i in allScripts) {
        var name = allScripts[i].src
        if(name && name.indexOf(scriptName) > 0)
            targetScripts.push(allScripts[i]);
    }

    scriptTag = targetScripts[targetScripts.length - 1];

    /******** Set jQuery noConflict *********/
    if (window.TGW === undefined || window.TGW.fn.jquery !== jqueryVersion) {
        loadScript(jqueryPath, initTGW);
    } else {
        initTGW();
    }

    function initTGW() {
        TGW = window.jQuery.noConflict(true);
        main();
    }

    function main() {
        TGW(document).ready(function ($) {
            loadParams();
        });
    }

    function loadParams() {
        jScript = TGW(scriptTag);
        comments = jScript.data("comment");
    }

})();

这里是它两次添加到网页的方式,评论数据属性的设置不同。

<script src='https://...my.widget.js' data-comment='yes'></script>
<script src='https://...my.widget.js' data-comment='no'></script>

根据上述情况,如果小部件中有一个假设按钮显示变量comments 的内容,则该变量将随机包含/显示“是”或“否”,具体取决于最后加载的小部件。

按下第一个小部件上的按钮时需要发生什么,是否显示“是”。当按下第二个小部件上的按钮时,它会显示“否”。

我认为这与命名空间或其他东西有关,但我不太了解。我认为将整个小部件包装在 (function () { 中作为匿名函数运行,这意味着所有变量都是独立的。

任何帮助表示赞赏

【问题讨论】:

  • 你可能应该检查一些设计模式,例如addyosmani.com/resources/essentialjsdesignpatterns/book/… 另外,你不应该像那样多次加载你的脚本 - 只需加载一次基本模块并调用它任意次数不同的参数。
  • @Alex.Me 这是其他用户将添加到他们自己网站的小部件,它不属于我自己的网站。不过,我会检查该链接。谢谢。

标签: javascript jquery namespaces widget


【解决方案1】:

在没有可靠的document.currentScript 的情况下,您可以尝试将allScripts = ....; for() {...} 替换为以下内容:

var marker = 'data-r_e_a_d'; // something unique, that won't overwrite any data- attribs delivered in the HTML

var scriptTag = Array.prototype.slice.call(document.getElementsByTagName('script')).reduce(function(prev, current) {
    var tag = (!prev && !current.getAttribute(marker) && current.src && current.src.indexOf(scriptName) > 0) ? current : prev;
    if(tag === current) current.setAttribute(marker, true);//mark "self" as read
    return tag;
}, null);

它将提供最新的未读限定脚本 - 即“self”。

在此过程之后,您的小部件的脚本标签中会留下标记属性。如果需要,可以在阅读最后一个 &lt;script&gt; 后清理这些内容,但将它们留在那里应该没有害处。

【讨论】:

    【解决方案2】:

    我相信您的scriptTag(对自我的引用)可能永远是页面上的最后一个脚本。

    如果您只支持较新的浏览器,您可以使用document.currentScript。否则,您可能必须为每个脚本标签分配一个唯一的 ID, 有关获取脚本参考https://stackoverflow.com/a/22745553/4297908 的不同方法,请参阅此答案。

    【讨论】:

    • 谢谢...document.currentScript 似乎根本没有得到广泛支持,不仅仅是 IE。这是其他非技术用户将添加到他们自己的网站等的小部件......在这种情况下,在脚本标签上使用唯一 ID 将不起作用。理想情况下,最终用户应该能够复制和粘贴脚本代码并将其添加到他们的站点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-28
    • 1970-01-01
    • 1970-01-01
    • 2013-06-15
    • 1970-01-01
    • 2011-02-09
    相关资源
    最近更新 更多