多次在页面上使用相同的小部件/变量冲突
Having the same widget on a page multiple time / variable clashes
我创建了一个 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
的内容,则该变量将随机contain/display "yes"或"no" 取决于最后加载的小部件。
按下第一个小部件上的按钮时需要发生什么,是否显示 "yes"。当按下第二个小部件上的按钮时,它显示 "no".
我认为这与名称空间或其他东西有关,但我不太明白。我认为将整个小部件包装在 运行 中制作的 (function () {
中作为匿名函数,这意味着所有变量都是独立的。
感谢任何帮助
我相信您的 scriptTag
(对自己的引用)可能始终是页面上的最后一个脚本。
如果您只支持较新的浏览器,则可以使用 document.currentScript
。否则你可能必须为每个脚本标签分配一个唯一的 id,
有关获取脚本参考 .
的不同方法,请参阅此答案
在没有可靠的 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"。
在此过程之后,此过程将在您的小部件的脚本标签中留下标记属性。如果需要,可以在阅读最后一个 <script>
后清除这些内容,但将它们留在那里应该没有什么坏处。
我创建了一个 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
的内容,则该变量将随机contain/display "yes"或"no" 取决于最后加载的小部件。
按下第一个小部件上的按钮时需要发生什么,是否显示 "yes"。当按下第二个小部件上的按钮时,它显示 "no".
我认为这与名称空间或其他东西有关,但我不太明白。我认为将整个小部件包装在 运行 中制作的 (function () {
中作为匿名函数,这意味着所有变量都是独立的。
感谢任何帮助
我相信您的 scriptTag
(对自己的引用)可能始终是页面上的最后一个脚本。
如果您只支持较新的浏览器,则可以使用 document.currentScript
。否则你可能必须为每个脚本标签分配一个唯一的 id,
有关获取脚本参考 .
在没有可靠的 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"。
在此过程之后,此过程将在您的小部件的脚本标签中留下标记属性。如果需要,可以在阅读最后一个 <script>
后清除这些内容,但将它们留在那里应该没有什么坏处。