我正在尝试动态加载 JS 脚本,但不能使用 jQuery。
我检查了 jQuery 源代码以了解getScript是如何实现的,以便我可以使用该方法使用本机 JS 加载脚本。但是,getScript 只调用 jQuery.get()
我一直无法找到 get 方法的实现位置。
所以我的问题是,
使用本机 JavaScript 实现我自己的 getScript 方法的可靠方法是什么?
谢谢!
我正在尝试动态加载 JS 脚本,但不能使用 jQuery。
我检查了 jQuery 源代码以了解getScript是如何实现的,以便我可以使用该方法使用本机 JS 加载脚本。但是,getScript 只调用 jQuery.get()
我一直无法找到 get 方法的实现位置。
所以我的问题是,
使用本机 JavaScript 实现我自己的 getScript 方法的可靠方法是什么?
谢谢!
这是具有回调功能的 jQuery getScript 替代方案:
function getScript(source, callback) {
var script = document.createElement('script');
var prior = document.getElementsByTagName('script')[0];
script.async = 1;
script.onload = script.onreadystatechange = function( _, isAbort ) {
if(isAbort || !script.readyState || /loaded|complete/.test(script.readyState) ) {
script.onload = script.onreadystatechange = null;
script = undefined;
if(!isAbort && callback) setTimeout(callback, 0);
}
};
script.src = source;
prior.parentNode.insertBefore(script, prior);
}
您可以像这样获取脚本:
(function(document, tag) {
var scriptTag = document.createElement(tag), // create a script tag
firstScriptTag = document.getElementsByTagName(tag)[0]; // find the first script tag in the document
scriptTag.src = 'your-script.js'; // set the source of the script to your script
firstScriptTag.parentNode.insertBefore(scriptTag, firstScriptTag); // append the script to the DOM
}(document, 'script'));
用这个
var js_script = document.createElement('script');
js_script.type = "text/javascript";
js_script.src = "http://www.example.com/script.js";
js_script.async = true;
document.getElementsByTagName('head')[0].appendChild(js_script);
首先,感谢@Mahn 的回答。我在 ES6 中重写了他的解决方案并Promise,如果有人需要它,我会在这里粘贴我的代码:
const loadScript = (source, beforeEl, async = true, defer = true) => {
return new Promise((resolve, reject) => {
let script = document.createElement('script');
const prior = beforeEl || document.getElementsByTagName('script')[0];
script.async = async;
script.defer = defer;
function onloadHander(_, isAbort) {
if (isAbort || !script.readyState || /loaded|complete/.test(script.readyState)) {
script.onload = null;
script.onreadystatechange = null;
script = undefined;
if (isAbort) { reject(); } else { resolve(); }
}
}
script.onload = onloadHander;
script.onreadystatechange = onloadHander;
script.src = source;
prior.parentNode.insertBefore(script, prior);
});
}
用法:
const scriptUrl = 'https://www.google.com/recaptcha/api.js?onload=onRecaptchaLoad&render=explicit';
loadScript(scriptUrl).then(() => {
console.log('script loaded');
}, () => {
console.log('fail to load script');
});
并且代码是 eslinted。
这里有一些很好的解决方案,但许多已经过时了。@Mahn有一个很好的,但正如评论中所述,它并不完全是替代品,$.getScript()
因为回调不接收数据。我已经编写了自己的函数来替代$.get()
并在我需要它为脚本工作时登陆这里。我能够使用@Mahn 的解决方案并与我当前的$.get()
替代品一起对其进行一些修改,并提出了一些运行良好且易于实现的方法。
function pullScript(url, callback){
pull(url, function loadReturn(data, status, xhr){
//If call returned with a good status
if(status == 200){
var script = document.createElement('script');
//Instead of setting .src set .innerHTML
script.innerHTML = data;
document.querySelector('head').appendChild(script);
}
if(typeof callback != 'undefined'){
//If callback was given skip an execution frame and run callback passing relevant arguments
setTimeout(function runCallback(){callback(data, status, xhr)}, 0);
}
});
}
function pull(url, callback, method = 'GET', async = true) {
//Make sure we have a good method to run
method = method.toUpperCase();
if(!(method === 'GET' || method === 'POST' || method === 'HEAD')){
throw new Error('method must either be GET, POST, or HEAD');
}
//Setup our request
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == XMLHttpRequest.DONE) { // XMLHttpRequest.DONE == 4
//Once the request has completed fire the callback with relevant arguments
//you should handle in your callback if it was successful or not
callback(xhr.responseText, xhr.status, xhr);
}
};
//Open and send request
xhr.open(method, url, async);
xhr.send();
}
现在我们有了一个替代品$.get()
,$.getScript()
它的工作方式同样简单:
pullScript(file1, function(data, status, xhr){
console.log(data);
console.log(status);
console.log(xhr);
});
pullScript(file2);
pull(file3, function loadReturn(data, status){
if(status == 200){
document.querySelector('#content').innerHTML = data;
}
}