让我们面对现实,jQuery / jQuery-ui是一个重载下载。
Google建议deferred loading of JavaScript加快初始呈现速度。我的页面使用jQuery来设置一些位于页面下方的选项卡(主要是在初始视图之外),我想将jQuery推迟到页面呈现之后。
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>
我想以这种方式推迟加载jQuery,但是当我尝试它时,我的jQuery代码无法找到jQuery(我不是完全出乎意料):
$(document).ready(function() {
$("#tabs").tabs();
});
所以,似乎我需要找到一种方法来推迟执行我的jQuery代码,直到加载jQuery。如何检测添加的标签是否已完成加载和解析?
作为必然结果,似乎asynchronous loading也可能包含答案。
有什么想法吗?
答案 0 :(得分:50)
试试这个,这是我之前从jQuerify bookmarklet编辑的。我经常使用它来加载jQuery并在加载后执行它们。你当然可以用你自己的url替换那里的url到你的自定义jquery。
(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
});
})();
我真的会将jQuery和jQuery-UI合并到一个文件中并使用它的URL。如果您真的想单独加载它们,只需链接getScripts:
getScript('http://myurltojquery.js',function(){
getScript('http://myurltojqueryUI.js',function(){
//your tab code here
})
});
答案 1 :(得分:13)
由于这是关于一个重要主题的排名最高的问题,让我根据@valmarv和@amparsand之前的回答,大胆地提出自己的看法。
我正在使用多维数组来加载脚本。将那些之间没有依赖关系的组合在一起:
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;
它在加载后加载第一个jquery,它会立即继续加载其他脚本。您可以通过在页面的任何位置添加到阵列来轻松添加脚本:
dfLoadFiles.push(["/js/loadbeforeA.js"]);
dfLoadFiles.push(["/js/javascriptA.js", "/js/javascriptB.js"]);
dfLoadFiles.push(["/js/loadafterB.js"]);
答案 2 :(得分:8)
以下是modern approach for async/defer javascript loading的详细说明。但它不适用于内联脚本
<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>
@nilskp - externalize script:
建议了最简单的异步加载解决方案<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>
答案 3 :(得分:3)
将jQuery和jQuery相关代码放在HTML文件的末尾。
编辑:更清晰
<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>
答案 4 :(得分:3)
element.addEventListener("load", function () {
$('#tabs').tabs()
}, false);
试试。
答案 5 :(得分:2)
在某些情况下,您可以在加载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>
然后将依赖项包装在函数中:
// 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);
}());
如果jquery在其他脚本之后加载完成,则在触发jqueryloaded事件时将执行依赖项。
如果已加载jquery jQueryHasLoaded === true
,则将执行您的依赖项initMyjQueryDependency()
。
答案 6 :(得分:1)
以下代码应在窗口加载后加载脚本:
<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>
在Chrome,FF和IE9中为我工作 - 让我知道是否有帮助
答案 7 :(得分:1)
在我看来,你需要做的就是a)添加你想在加载时运行的jQuery代码,到jQuery文件的末尾或者b)将它附加到downloadJSAtOnload
函数中这样:
<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);
$("#tabs").tabs(); // <==== NOTE THIS. This should theoretically run after the
// script has been appended, though you'll have to test this
// because I don't know if the JavaScript above will wait for
// the script to load before continuing
}
// 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>
答案 8 :(得分:1)
这是我的版本,它支持链接,以确保脚本一个接一个地加载,基于&符号的代码:
var deferredJSFiles = ['jquery/jquery', 'file1', 'file2', 'file3'];
function downloadJSAtOnload() {
if (!deferredJSFiles.length)
return;
var deferredJSFile = deferredJSFiles.shift();
var element = document.createElement('script');
element.src = deferredJSFile.indexOf('http') == 0 ? deferredJSFile : '/js/' + deferredJSFile + '.js';
element.onload = element.onreadystatechange = function() {
if (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete')
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;
答案 9 :(得分:1)
<!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>
答案 10 :(得分:1)
我认为Modernizr.load()在这里值得一提 - 它非常好地处理依赖加载
答案 11 :(得分:1)
Google Analytics(分析)使用了一个简单的技巧。
1。。在HTML的头部添加一个小脚本
<script>
window.jQuery_store = [];
window.jQueryReady = function (fn) { jQuery_store.push(fn); }
</script>
jQueryReady函数会将委托保存到数组中以备将来使用。
2。。创建具有下一个内容的新JS脚本jquery-ready.js
:
// When jQuery is finaly ready
$(function() {
// Replace previous implementation
window.jQueryReady = function(fn) {
// jQuery is loaded call immediately
fn();
}
// Call all saved callbacks
for (var i = 0; i < window.jQuery_store.length; ++i) {
try {
window.jQuery_store[i]();
} catch (err) {
console.log(err);
}
}
})
加载此脚本后,它将:
jQuery
可以安全使用jQueryReady
替换为新函数,该函数立即调用委托(jQuery在指定时间准备就绪)。jQueryReady
个调用中保存的函数。3。 仅在加载jQuery之后才使jquery-ready.js加载。 在页脚中,您将拥有:
<script defer src=".../jquery.min.js">
<script defer src=".../bootstrap.min.js">
... any other plugins for jQuery you probably need
<script defer src=".../jquery-ready.js">
这可以确保仅在执行jQuery之后才执行jquery-ready.js脚本。
现在您可以随时使用jQueryReady函数。
jQueryReady(function() {
// jQuery is safe to use here
$("div.to-be-hidden").hide();
})
答案 12 :(得分:0)
似乎您需要<script defer>
:http://www.w3schools.com/tags/att_script_defer.asp
答案 13 :(得分:0)
看看jQuery.holdReady()
“保存或释放jQuery的ready事件的执行。” (jQuery 1.6 +)
答案 14 :(得分:0)
我在async / defered jquery脚本标记之后添加了这段代码,这定义了一个临时函数$,它将累积任何在完成所有内容时需要运行的内容,然后一旦我们完成使用$ that此时将被覆盖以执行这些功能。使用这段代码,无需在文档中进一步更改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>
....然后......
<script>
$(function() {
alert("loaded");
});
</script>
答案 15 :(得分:-2)
使用http://labjs.com加载html末尾的所有脚本,这是100%的解决方案,我对gtmetrix规则进行了多次测试。例如http://gtmetrix.com/reports/interactio.cz/jxomHSLV