cgreact-loader
Version:
CGReact与Webpack配套的loader
74 lines (73 loc) • 2.55 kB
JavaScript
/** 当页面同时加载2个JSONP标签的时候
* 浏览器会随机选择某一个标签先执行,造成JS执行乱序问题
* 所以定义一个同步队列,保证JS的执行顺序按照用户调用的顺序
*/
const SyncJSLoad = {
loadFlag: false,
jsTagQue: new Array(),
start: () =>
{
// 正在加载或者队列里没有需要加载的,就不管了
if (SyncJSLoad.loadFlag || SyncJSLoad.jsTagQue.length <= 0)
{
// 如果是正在加载JS,会在onload的时候重新调用此方法
return;
}
// 否则继续按顺序加载
SyncJSLoad.loadFlag = true;
document.body.appendChild(SyncJSLoad.jsTagQue.shift());
}
}
// 开始构建返回结果
let script = cg_exports;
let result = {};
result.script = script;
/** JS的加载方式与CSS相比是不同的
* 即使是同一个CSS的<link>标签对象,只要被放置在页面上css就会生效,所以只需控制好一个标签的添加删除
* JS的<script>标签则不同,如果是同一个标签,只会在第一次放到页面上的时候执行JS代码,第二次则不会
* 因此必须每一次都创建一个新的<script>标签,移除的时候,也要考虑多次加载的问题(多次加载的标签是不同的对象)
*/
result.affect = (context) =>
{
// 如果加载过首先移除,防止连续调用affect()出现多个相同标签(不同对象)
result.invalid();
// 用jsonp的方式加载
let tag = document.createElement("script");
tag.setAttribute("type", "text/javascript");
tag.setAttribute("id", script);
tag.setAttribute("src", script);
tag.onload = function ()
{
SyncJSLoad.loadFlag = false;
SyncJSLoad.start();
}
// 唤醒队列加载标签
SyncJSLoad.jsTagQue.push(tag);
SyncJSLoad.start();
// 重载上下文钩子做自动移除
if (context)
{
result.bind(context);
}
return result;
};
result.invalid = () =>
{
let tag = document.getElementById(script);
while (tag)
{
tag.remove();
tag = document.getElementById(script);
}
return result;
};
// 重载上下文的钩子函数,做离开页面自动移除的效果
result.bind = (context) =>
{
if (context && context.CssAndJSList && typeof context.CssAndJSList.push == "function")
{
context.CssAndJSList.push(result);
}
return result;
};
module.exports = result;