目录
JavaScript文件的动态加载是您必须拥有的非常有用的工具之一。它允许您通过将阻止脚本从加载过程中移出(通常称为“延迟加载”)来优化网页性能,并仅在用户需要时加载脚本(通常称为“按需加载”)。如果您明智地使用此工具,它将大大提高您的页面性能。
配置
让我们定义我们的示例模型,我们将从定义需要动态加载的远程文件开始。这是“remote.js”文件的定义:
// this is going to be executed when script is loaded
(function () {
console.log("Remote script loaded");
}());
var sayHello = function (name) {
alert("Hello", name);
}
在上面的代码中,我们定义了一个直接函数来跟踪文件加载。我们还定义了一个从主页面调用的自定义函数。
现在,这是我们的主要“index.htm”页面。它只包含一个用于加载和测试文件的按钮。
<html>
<head>
</head>
<body>
<button id="loadButton">Load script file</button>
<script type="text/javascript">
document.getElementById('loadButton').onclick = function () {
// your code goes here
};
</script>
</body>
</html>
无脑方法!
加载JavaScript文件最直接的方法是在<script>元素中引用它。动态加载这个文件最简单的方法就是动态加载这个元素!
让我们更新代码并查看实际结果:
document.getElementById("loadButton").onclick = function () {
var script = document.createElement("script");
script.src = "remote.js";
script.onload = function () {
sayHello("Mohammad");
};
// append and execute script
document.documentElement.firstChild.appendChild(script);
};
上面的代码简单地创建了一个<script>元素并将这个元素的src字段设置为我们文件的路径。然后它使用该appendChild()函数将其附加到我们代码的第一个子<head>元素元素。以下代码产生以下结果:
现在,让我们重构上面的代码并稍微修改一下,以便能够在其他任何地方使用它:
/**
* Used to load and execute javascript file. an be used cross-domain seamlessly.
* @param file JS file name
* @param callback Subscribe to get notified when script file is loaded
**/
function require(file, callback) {
// create script element
var script = document.createElement("script");
script.src = file;
// monitor script loading
// IE < 7, does not support onload
if (callback) {
script.onreadystatechange = function () {
if (script.readyState === "loaded" || script.readyState === "complete") {
// no need to be notified again
script.onreadystatechange = null;
// notify user
callback();
}
};
// other browsers
script.onload = function () {
callback();
};
}
// append and execute script
document.documentElement.firstChild.appendChild(script);
}
document.getElementById("loadButton").onclick = function () {
require("remote.js", function () {
sayHello("Mohammad");
});
};
现在,您可以轻松调用require()以及JavaScript 路径和回调函数,以便在加载脚本时收到通知。
逆袭之道!
动态加载JavaScript文件的另一种方法是使用经典HTTP请求检索它。这是一个纯JavaScript调用,但它有很多缺点。让我们看看它的实际效果:
/**
* Used to load and execute javascript file. Suffers from same-domain restriction.
* @param file JS file name
* @param callback Subscribe to get notified when script file is loaded
**/
function requireXhr(file, callback) {
// object initialization
const xhr = new XMLHttpRequest();
// subscribe to request events
xhr.onreadystatechange = function () {
// readyState:
// 0 UNSENT Client has been created. open() not called yet.
// 1 OPENED open() has been called.
// 2 HEADERS_RECEIVED send() has been called, and headers and status are available.
// 3 LOADING Downloading; responseText holds partial data.
// 4 DONE The operation is complete.
// when not done, return
if (xhr.readyState !== 4) {
return;
}
// done, check status code
if (xhr.status !== 200) // 200 = OK
{
return;
}
// now the file is loaded,
// go and execute the script
eval(xhr.responseText);
// notify caller
if (callback) {
callback();
}
};
// open connection to file
xhr.open("GET", file, true);
// send the request
xhr.send();
}
document.getElementById("loadButton").onclick = function () {
requireXhr("remote.js", function () {
sayHello("Mohammad");
});
};
该代码非常简单且具有自我描述性。我们使用XMLHttpRequest对象设置一个HTML请求,然后触发它。然后,我们监控其状态变化并相应地执行。
当我们执行上面的代码时,我们得到以下结果。我们可以在DevTools扩展中看到我们成功的XHR请求:
另一方面,结果令人失望。我们能够成功运行脚本,并且HTML内容中没有脚本文件的线索,但是,由于eval()的私有范围,我们无法调用加载的函数。
这种方式的其他缺点是它在跨域工作时会受到很大影响。而且您也不能从本地路径加载!
一块蛋糕!
现在是最直接的延迟加载JavaScript文件的方式,jQuery方式。jQuery提供了一个名为getScript()(它是ajax()的简写)的函数来检索和加载JavaScript文件。这是代码:
/**
* Used to load and execute JavaScript file.
* @param file JS file name
* @param callback Subscribe to get notified when script file is loaded
**/
function requireAjax(file, callback) {
jQuery.getScript(file, callback);
}
document.getElementById("loadButton").onclick = function () {
requireAjax("remote.js", function () {
sayHello("Mohammad");
});
};
虽然jQuery.getScript() 在内部使用XMLHttpRequest,并且您可以在DevTools中的XHR列表中看到请求,但它没有XMLHttpRequest那样的缺点(比如同域限制)。它比原始的XMLHttpRequest更容易使用和执行。
结果也很棒:
结论
总而言之,如果您在页面中启用了jQuery,您就可以轻松地使用jQuery.getScript()按需异步加载JavaScript。如果您正在寻找一种纯JavaScript方法,请选择这种<script>方法,它产生的开销很小。
源代码
该示例可在GitHub上的以下位置获得:
https://www.codeproject.com/Articles/5310336/Dynamically-Loading-a-JavaScript-File