ILi*_*cos 44 javascript jquery getscript
我正在尝试动态加载JS脚本,但使用jQuery不是一个选项.
我检查了jQuery源代码以了解如何实现getScript,以便我可以使用该方法使用本机JS加载脚本.但是,getScript只调用jQuery.get()
而且我无法找到get方法的实现位置.
所以我的问题是,
使用本机JavaScript实现自己的getScript方法的可靠方法是什么?
谢谢!
Mah*_*ahn 84
这是一个带回调功能的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);
}
Run Code Online (Sandbox Code Playgroud)
Mat*_*ics 30
你可以像这样获取脚本:
(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'));
Run Code Online (Sandbox Code Playgroud)
小智 11
首先,感谢@ Mahn的回答.我在ES6中重写了他的解决方案并承诺,如果有人需要它,我将在这里粘贴我的代码:
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);
});
}
Run Code Online (Sandbox Code Playgroud)
用法:
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');
});
Run Code Online (Sandbox Code Playgroud)
并且代码是精确的.
用这个
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);
Run Code Online (Sandbox Code Playgroud)
这里有一些很好的解决方案,但许多已经过时了。@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();
}
Run Code Online (Sandbox Code Playgroud)
现在我们有了一个替代品$.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;
}
}
Run Code Online (Sandbox Code Playgroud)
这完善了以前的 ES6 解决方案,并将适用于所有现代浏览器
const getScript = url => new Promise((resolve, reject) => {
const script = document.createElement('script')
script.src = url
script.async = true
script.onerror = reject
script.onload = script.onreadystatechange = function() {
const loadState = this.readyState
if (loadState && loadState !== 'loaded' && loadState !== 'complete') return
script.onload = script.onreadystatechange = null
resolve()
}
document.head.appendChild(script)
})
Run Code Online (Sandbox Code Playgroud)
getScript('https://dummyjs.com/js')
.then(() => {
console.log('Loaded', dummy.text())
})
.catch(() => {
console.error('Could not load script')
})
Run Code Online (Sandbox Code Playgroud)
也适用于 JSONP 端点
const callbackName = `_${Date.now()}`
getScript('http://example.com/jsonp?callback=' + callbackName)
.then(() => {
const data = window[callbackName];
console.log('Loaded', data)
})
Run Code Online (Sandbox Code Playgroud)
另外,请注意列出的一些 AJAX 解决方案,因为它们绑定到现代浏览器中的 CORS 策略https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS