Можно ли отложить загрузку jQuery?
давайте посмотрим правде в глаза, jQuery/jQuery-ui-это тяжелая загрузка.
Google рекомендует отложенная загрузка JavaScript для ускорения начального рендеринга. Моя страница использует jQuery для настройки некоторых вкладок, которые размещаются низко на странице (в основном из начального представления), и я хотел бы отложить jQuery до тех пор, пока страница не будет отображена.
код отсрочки Google добавляет тег в DOM после загрузки страницы, подключаясь к событию body onLoad:
<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 не будет загружен. Как я могу определить, что добавленный тег закончил загрузку и разбор?
как следствие, оказывается, что асинхронная загрузка может также содержать ответ.
какие мысли?
15 ответов:
попробуйте это, что я редактировал некоторое время назад из букмарклета jQuerify. Я часто использую его для загрузки 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 }) });
поскольку это вопрос высшего ранга по важному вопросу, позвольте мне быть настолько смелым, чтобы предоставить свое собственное мнение об этом на основе предыдущего ответа от @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"]);
вот хорошее описание современный подход для асинхронной / отложенной загрузки 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>
самое простое решение для асинхронной загрузки было предложено скриптом @ 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>
поместите jQuery и ваш зависимый от jQuery код в конец вашего HTML-файла.
Edit: немного более ясно
<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>
в определенной ситуации вы можете запустить событие при загрузке 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()
.
Ну, мне кажется, все, что вам нужно сделать, это либо a) добавить код jQuery, который вы хотите запустить при загрузке, в конец файла jQuery, либо b) добавить его в
следующий код должен загрузить ваши скрипты после завершения загрузки окна:
<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-дайте мне знать, если это поможет
вот моя версия, которая поддерживает, чтобы убедиться, что скрипты загружаются один за другим, на основе амперсандС:
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;
<!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>
Я думаю, что Modernizr.load () стоит упомянуть здесь - он обрабатывает загрузку зависимостей очень хорошо
Кажется, что вам просто нужно
<script defer>
: http://www.w3schools.com/tags/att_script_defer.asp
посмотреть
jQuery.holdReady()
" удерживает или освобождает выполнение события готовности jQuery."(jQuery 1.6+)
Я добавляю этот фрагмент кода после тега async / defered jQuery script, это определяет временную функцию $, которая будет накапливать все, что нужно для запуска, когда все будет загружено, а затем, как только мы закончим использовать$, который к этому времени будет перезаписан для выполнения функций. С помощью этого фрагмента кода нет необходимости изменять синтаксис 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>
Загрузите все скрипты в конце html с помощью http://labjs.com, это 100% решение, и я тестировал его много раз против правил gtmetrix. пример http://gtmetrix.com/reports/interactio.cz/jxomHSLV