Javascript 可以推迟 jQuery 的加载吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5852767/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Possible to defer loading of jQuery?
提问by Kevin P. Rice
Let's face it, jQuery/jQuery-ui is a heavy download.
让我们面对现实吧,jQuery/jQuery-ui 下载量很大。
Google recommends deferred loading of JavaScriptto speed up initial rendering. My page uses jQuery to set up some tabs which are placed low on the page (mostly out of initial view) and I'd like to defer jQuery until AFTER the page has rendered.
Google 建议延迟加载 JavaScript以加速初始渲染。我的页面使用 jQuery 来设置一些位于页面较低位置的选项卡(大部分在初始视图之外),我想将 jQuery 推迟到页面呈现后。
Google's deferral code adds a tag to the DOM after the page loads by hooking into the body onLoad event:
Google 的延迟代码在页面加载后通过挂钩主体 onLoad 事件向 DOM 添加一个标记:
<script type="text/javascript">
// Add a script element as a child of the body
function downloadJSAtOnload() {
var element = document.createElement("script");
element.src = "deferredfunctions.js";
document.body.appendChild(element);
}
// Check for browser support of event handling capability
if (window.addEventListener)
window.addEventListener("load", downloadJSAtOnload, false);
else if (window.attachEvent)
window.attachEvent("onload", downloadJSAtOnload);
else window.onload = downloadJSAtOnload;
</script>
I'd like to defer loading of jQuery this way, but when I tried it my jQuery code failed to find jQuery (not completely unexpected on my part):
我想以这种方式推迟 jQuery 的加载,但是当我尝试它时,我的 jQuery 代码未能找到 jQuery(这对我来说并不完全出乎意料):
$(document).ready(function() {
$("#tabs").tabs();
});
So, it seems I need to find a way to defer execution of my jQuery code until jQuery is loaded. How do I detect that the added tag has finished loading and parsing?
所以,似乎我需要找到一种方法来推迟我的 jQuery 代码的执行,直到 jQuery 被加载。如何检测添加的标签是否已完成加载和解析?
As a corollary, it appears that asynchronous loadingmay also contain an answer.
作为推论,异步加载似乎也包含一个答案。
Any thoughts?
有什么想法吗?
采纳答案by ampersand
Try this, which is something I edited a while ago from the jQuerify bookmarklet. I use it frequently to load jQuery and execute stuff after it's loaded. You can of course replace the url there with your own url to your customized jquery.
试试这个,这是我不久前从 jQuerify 书签中编辑的内容。我经常使用它来加载 jQuery 并在加载后执行内容。您当然可以将那里的 url 替换为您自己的自定义 jquery 的 url。
(function() {
? function getScript(url,success){
? ? var script=document.createElement('script');
? ? script.src=url;
? ? var head=document.getElementsByTagName('head')[0],
? ? ? ? done=false;
? ? script.onload=script.onreadystatechange = function(){
? ? ? if ( !done && (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete') ) {
? ? ? ? done=true;
? ? ? ? success();
? ? ? ? script.onload = script.onreadystatechange = null;
? ? ? ? head.removeChild(script);
? ? ? }
? ? };
? ? head.appendChild(script);
? }
getScript('http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js',function(){
// YOUR CODE GOES HERE AND IS EXECUTED AFTER JQUERY LOADS
});
})();
I would really combine jQuery and jQuery-UI into one file and use a url to it. If you REALLY wanted to load them separately, just chain the getScripts:
我真的会将 jQuery 和 jQuery-UI 合并到一个文件中,并使用一个 url。如果您真的想单独加载它们,只需链接 getScripts:
getScript('http://myurltojquery.js',function(){
getScript('http://myurltojqueryUI.js',function(){
//your tab code here
})
});
回答by Pevawi
As this is a top ranking question on a important subject let me be so bold to provide my own take on this based on a previous answer from @valmarv and @amparsand.
由于这是一个重要主题的排名靠前的问题,让我大胆地根据@valmarv 和@amparsand 的先前回答提供我自己的看法。
I'm using a multi-dimensional array to load the scripts. Grouping together those that have no dependencies between them:
我正在使用多维数组来加载脚本。将它们之间没有依赖关系的那些组合在一起:
var dfLoadStatus = 0;
var dfLoadFiles = [
["http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"],
["http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/jquery-ui.min.js",
"/js/somespecial.js",
"/js/feedback-widget.js#2312195",
"/js/nohover.js"]
];
function downloadJSAtOnload() {
if (!dfLoadFiles.length) return;
var dfGroup = dfLoadFiles.shift();
dfLoadStatus = 0;
for(var i = 0; i<dfGroup.length; i++) {
dfLoadStatus++;
var element = document.createElement('script');
element.src = dfGroup[i];
element.onload = element.onreadystatechange = function() {
if ( ! this.readyState ||
this.readyState == 'complete') {
dfLoadStatus--;
if (dfLoadStatus==0) downloadJSAtOnload();
}
};
document.body.appendChild(element);
}
}
if (window.addEventListener)
window.addEventListener("load", downloadJSAtOnload, false);
else if (window.attachEvent)
window.attachEvent("onload", downloadJSAtOnload);
else window.onload = downloadJSAtOnload;
It loads first jquery after it is loaded it continue to load the other scripts at once. You can add scripts easy by adding to the array anywhere on your page:
它在加载后首先加载 jquery,然后继续立即加载其他脚本。您可以通过添加到页面上任意位置的数组来轻松添加脚本:
dfLoadFiles.push(["/js/loadbeforeA.js"]);
dfLoadFiles.push(["/js/javascriptA.js", "/js/javascriptB.js"]);
dfLoadFiles.push(["/js/loadafterB.js"]);
回答by Grigory Kislin
Here is a good description of modern approach for async/defer javascript loading. But it doesn't works for inline scripts
这里很好地描述了异步/延迟 javascript 加载的现代方法。但它不适用于内联脚本
<script type="text/javascript" src="/jquery/3.1.1-1/jquery.min.js" defer></script>
<script type="text/javascript" defer>
$(function () { // <- jquery is not yet initialized
...
});
</script>
The simplest solution for async loading was suggested by @nilskp - externalize script:
@nilskp 建议了最简单的异步加载解决方案 - externalize 脚本:
<script type="text/javascript" src="/jquery/3.1.1-1/jquery.min.js" defer></script>
<script type="text/javascript" src="resources/js/onload.js" defer></script>
回答by McKayla
element.addEventListener("load", function () {
$('#tabs').tabs()
}, false);
Try that.
试试那个。
回答by Dan
Put jQuery and your jQuery dependent code at the end of your HTML file.
将 jQuery 和您的 jQuery 相关代码放在 HTML 文件的末尾。
Edit: A little more clear
编辑:更清楚一点
<html>
<head></head>
<body>
<!-- Your normal content here -->
<script type="text/javascript" src="http://path/to/jquery/jquery.min.js"></script>
<script>//Put your jQuery code here</script>
</body>
</html>
回答by asiop
I add this piece of code after the async/defered jquery script tag, this defines a temporary function $ that will accumulate whatever it is that needs to run when everything is done loading, and then once we're done use $ that by this time would be overwritten to execute the functions. With this piece of code there's no need to change the jQuery onload syntax further down in the document.
我在 async/defered jquery 脚本标签之后添加了这段代码,它定义了一个临时函数 $,它将在一切加载完成后累积它需要运行的任何内容,然后一旦我们完成,此时使用 $将被覆盖以执行功能。使用这段代码,无需在文档中进一步更改 jQuery onload 语法。
<script defer async src="https://code.jquery.com/jquery-2.2.0.min.js">
<script>
var executeLater = [];
function $(func) {
executeLater.push(func);
}
window.addEventListener('load', function () {
$(function () {
for (var c = 0; c < executeLater.length; c++) {
executeLater[c]();
}
});
})
</script>
....and then...
....进而...
<script>
$(function() {
alert("loaded");
});
</script>
回答by mex23
In certain situation you could fire an event when jquery is loaded.
在某些情况下,您可以在加载 jquery 时触发事件。
<script type="text/javascript">
(function (window) {
window.jQueryHasLoaded = false;
document.body.addEventListener('jqueryloaded', function (e) {
console.log('jqueryloaded ' + new Date() );
}, false);
function appendScript(script) {
var tagS = document.createElement("script"),
s = document.getElementsByTagName("script")[0];
tagS.src = script.src;
s.parentNode.insertBefore(tagS, s);
if ( script.id == 'jquery' ) {
tagS.addEventListener('load', function (e) {
window.jQueryHasLoaded = true;
var jQueryLoaded = new Event('jqueryloaded');
document.body.dispatchEvent(jQueryLoaded);
}, false);
}
}
var scripts = [
{
'id': 'jquery',
'src': 'js/libs/jquery/jquery-2.0.3.min.js'
},
{
'src': 'js/myscript1.js'
},
{
'src': 'js/myscript2.js'
}
];
for (var i=0; i < scripts.length; i++) {
appendScript(scripts[i]);
}
}(window));
</script>
Then wrap your dependencies in a function:
然后将您的依赖项包装在一个函数中:
// myscript1.js
(function(){
function initMyjQueryDependency() {
console.log('my code is executed after jquery is loaded!');
// here my code that depends on jquery
}
if ( jQueryHasLoaded === true )
initMyjQueryDependency();
else
document.body.addEventListener('jqueryloaded', initMyjQueryDependency, false);
}());
If jquery finishes to load after the other scripts, your dependencies will be executed when the jqueryloaded event is fired.
如果 jquery 在其他脚本之后完成加载,则在触发 jqueryloaded 事件时将执行您的依赖项。
If jquery is already loaded, jQueryHasLoaded === true
, your dependency will be executed initMyjQueryDependency()
.
如果 jquery 已加载,jQueryHasLoaded === true
则将执行您的依赖项initMyjQueryDependency()
。
回答by Nanhe Kumar
<!doctype html>
<html>
<head>
</head>
<body>
<p>If you click on the "Hide" button, I will disappear.</p>
<button id="hide" >Hide</button>
<button id="show" >Show</button>
<script type="text/javascript">
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.body.appendChild(script);
}
loadScript("http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js",
function() {
//YAHOO.namespace("mystuff");
$("#show").click(function() {
$("p").show();
});
$("#hide").click(function() {
$("p").hide();
});
//more...
});
</script>
</body>
</html>
回答by Mike
I think Modernizr.load() is worth a mention here - it handles dependency loading very nicely
我认为 Modernizr.load() 在这里值得一提——它可以很好地处理依赖加载
回答by Jeremy Battle
The following code should load your scripts after the window is finished loading:
以下代码应在窗口完成加载后加载您的脚本:
<html>
<head>
<script>
var jQueryLoaded = false;
function test() {
var myScript = document.createElement('script');
myScript.type = 'text/javascript';
myScript.async = true;
myScript.src = jQueryLoaded ? 'http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.js' : 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/jquery-ui.min.js';
document.body.appendChild(myScript);
if(!jQueryLoaded){
alert('jquery was loaded');
jQueryLoaded = true;
test();
} else {
alert('jqueryui was loaded');
}
}
if (window.addEventListener){
alert('window.addEventListener');
window.addEventListener("load", test, false);
} else if (window.attachEvent){
alert('window.attachEvent');
window.attachEvent("onload", test);
} else{
alert('window.onload');
window.onload = test;
}
</script>
</head>
<body>
<p>Placeholder text goes here</p>
</body>
</html>
Worked for me in Chrome, FF and IE9 - let me know if that helps
在 Chrome、FF 和 IE9 中为我工作 - 如果有帮助,请告诉我