文章目录
背景
为了便捷用户使用sdk引入js文件没有用,从用户角度想简化引入各类css、js库的麻烦琐事。
问题来了,用document.write可以完美解决这个问题,但问题的问题是即使浏览器有警告,但它还是执行了,就不晓得哪三天会不会直接error出现或则拦截了。
最好的方法其实是采用es6使用import模块的方法,这儿是考虑了老的加载形式,即直接通过引入script标签引入js库。
现实情况是难免会有用到引入第三方库的情况。
这儿也不考虑使用requirejs的方法引入js文件没有用,由于用了这个还不如直接用es6自带的import来的快。
Whyyoushouldavoidusingdocument.write,specificallyforscriptsinjection
var sNew = document.createElement("script");
sNew.async = true;
sNew.src = "https://example.com/script.min.js";
var s0 = document.getElementsByTagName('script')[0];
s0.parentNode.insertBefore(sNew, s0);
解决方案1目前暂可行的施行方案
// 动态加载js脚本文件
function loadScript(url) {
document.write(`\x3Cscript type="text/javascript" src="${url}">\x3C/script>`);
}
// 动态加载css文件
function loadStyles(url) {
document.write(
`\x3Clink type="text/css" rel="stylesheet" href="${url}">\x3C/link>`
);
}
(function () {
loadStyles(ipconfig + "/css/a.css");
loadStyles(ipconfig + "/css/b.css");
loadScript(ipconfig + "/lib/a.js");
loadScript(ipconfig + "/lib/b.js");})();
2反弹函数
意味着要使用使用第三方的对象须要在反弹函数中使用
function loadScript(url, callback){
var script = document.createElement ("script")
script.type = "text/javascript";
if (script.readyState){ //IE
script.onreadystatechange = function(){
if (script.readyState == "loaded" || script.readyState == "complete"){
script.onreadystatechange = null;
callback();
}
};
} else { //Others
script.onload = function(){
callback();
};
}
script.src = url;
document.getElementsByTagName("head")[0].appendChild(script);
}
loadScript(urlCesium, function(){alert('加载成功')});
3异步加载
写法1ol中的使用方式
class LazyLoader {
/**
* @param {string} url
* @api
*/
constructor(url) {
/**
* @type {Promise}
* @protected
*/
this.promise;
/**
* @private
* @type {string}
*/
this.url_ = url;
}
/**
* @return {Promise}
* @api
*/
load() {
if (!this.promise) {
// not yet loading
this.promise = new Promise((resolve, reject) => {
const script = document.createElement("script");
script.onload = () => resolve();
script.onerror = () => reject();
document.head.appendChild(script);
script.src = this.url_;
});
}
return this.promise;
}
}
const url = "http://localhost:9300/a.js";
const aLazyLoader = new LazyLoader(url);
var a = cesiumLazyLoader.load().then(() => console.log('使用a模块中的对象'));
写法2Cesium中的使用方式
/**
* @private
*/
function loadAndExecuteScript(url) {
var deferred = when.defer();
var script = document.createElement("script");
script.async = true;
script.src = url;
var head = document.getElementsByTagName("head")[0];
script.onload = function () {
script.onload = undefined;
head.removeChild(script);
deferred.resolve();
};
script.onerror = function (e) {
deferred.reject(e);
};
head.appendChild(script);
return deferred.promise;
}
export default loadAndExecuteScript;
// 使用方法
var url = buildModuleUrl("ThirdParty/google-earth-dbroot-parser.js");
var oldValue = window.cesiumGoogleEarthDbRootParser;
var dbrootParserPromise = loadAndExecuteScript(url).then(function () {
dbrootParser = window.cesiumGoogleEarthDbRootParser(protobufMinimal);
if (defined(oldValue)) {
window.cesiumGoogleEarthDbRootParser = oldValue;
} else {
delete window.cesiumGoogleEarthDbRootParser;
}
});
结束语
虽然使用es6的模块化+异步的方式能更好的解决这个问题。假如有其他办法后续再说吧
参考文章
Iamdynamicallyaddingascriptofagithubgist.IfIaddedittothehtmlbeforethepageloads,thescriptwillexecute.ButIfItrytoaddittothepageafteritloadsitaddsthescripttothepagebutdoesn’texecuteit.
js动态加载第三方js库(带onload功能)
动态插入的script脚本执行时间
editorJs2.async=false
动态加载js不执行解决办法(测试不成功)
这个问题的形成缘由是:我们项目有一个主index文件,在主index文件中须要依照参数来判定是加载pc.html的内容还是加载mobile.html的内容,一开始是使用jquery来做的,没有问题,后来想着jquery也有80多k就想着优化下,结果将所有有$的地方都转为原生的js代码,js,css,dom也都加载正常,就是页面显示不下来,动态加载的js没有执行,查了很长时间才找到方案,如上图;