$ (document). уже эквивалент без jQuery
У меня есть script, который использует $(document).ready
, но он не использует ничего из jQuery. Я хотел бы осветлить его, удалив зависимость jQuery.
Как я могу реализовать свои собственные функции $(document).ready
без использования jQuery? Я знаю, что использование window.onload
не будет таким же, как window.onload
запускается после загрузки всех изображений, кадров и т.д.
Ответы
Ответ 1
Существует замена на основе стандартов DOMContentLoaded
, которая поддерживается более чем 98% браузеров, хотя не IE8:
document.addEventListener("DOMContentLoaded", function(event) {
//do work
});
Функция jQuery native намного сложнее, чем просто window.onload, как показано ниже.
function bindReady(){
if ( readyBound ) return;
readyBound = true;
// Mozilla, Opera and webkit nightlies currently support this event
if ( document.addEventListener ) {
// Use the handy event callback
document.addEventListener( "DOMContentLoaded", function(){
document.removeEventListener( "DOMContentLoaded", arguments.callee, false );
jQuery.ready();
}, false );
// If IE event model is used
} else if ( document.attachEvent ) {
// ensure firing before onload,
// maybe late but safe also for iframes
document.attachEvent("onreadystatechange", function(){
if ( document.readyState === "complete" ) {
document.detachEvent( "onreadystatechange", arguments.callee );
jQuery.ready();
}
});
// If IE and not an iframe
// continually check to see if the document is ready
if ( document.documentElement.doScroll && window == window.top ) (function(){
if ( jQuery.isReady ) return;
try {
// If IE is used, use the trick by Diego Perini
// http://javascript.nwbox.com/IEContentLoaded/
document.documentElement.doScroll("left");
} catch( error ) {
setTimeout( arguments.callee, 0 );
return;
}
// and execute any waiting functions
jQuery.ready();
})();
}
// A fallback to window.onload, that will always work
jQuery.event.add( window, "load", jQuery.ready );
}
Ответ 2
Редактировать:
Вот жизнеспособная замена для JQuery готов
function ready(callback){
// in case the document is already rendered
if (document.readyState!='loading') callback();
// modern browsers
else if (document.addEventListener) document.addEventListener('DOMContentLoaded', callback);
// IE <= 8
else document.attachEvent('onreadystatechange', function(){
if (document.readyState=='complete') callback();
});
}
ready(function(){
// do something
});
Взято с https://plainjs.com/javascript/events/running-code-when-the-document-is-ready-15/
Еще одна хорошая функция domReady, взята с fooobar.com/questions/2793/...
Поскольку принятый ответ был очень далек от завершения, я jQuery.ready()
"готовую" функцию, такую как jQuery.ready()
основанную на источнике jQuery 1.6.2:
var ready = (function(){
var readyList,
DOMContentLoaded,
class2type = {};
class2type["[object Boolean]"] = "boolean";
class2type["[object Number]"] = "number";
class2type["[object String]"] = "string";
class2type["[object Function]"] = "function";
class2type["[object Array]"] = "array";
class2type["[object Date]"] = "date";
class2type["[object RegExp]"] = "regexp";
class2type["[object Object]"] = "object";
var ReadyObj = {
// Is the DOM ready to be used? Set to true once it occurs.
isReady: false,
// A counter to track how many items to wait for before
// the ready event fires. See #6781
readyWait: 1,
// Hold (or release) the ready event
holdReady: function( hold ) {
if ( hold ) {
ReadyObj.readyWait++;
} else {
ReadyObj.ready( true );
}
},
// Handle when the DOM is ready
ready: function( wait ) {
// Either a released hold or an DOMready/load event and not yet ready
if ( (wait === true && !--ReadyObj.readyWait) || (wait !== true && !ReadyObj.isReady) ) {
// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
if ( !document.body ) {
return setTimeout( ReadyObj.ready, 1 );
}
// Remember that the DOM is ready
ReadyObj.isReady = true;
// If a normal DOM Ready event fired, decrement, and wait if need be
if ( wait !== true && --ReadyObj.readyWait > 0 ) {
return;
}
// If there are functions bound, to execute
readyList.resolveWith( document, [ ReadyObj ] );
// Trigger any bound ready events
//if ( ReadyObj.fn.trigger ) {
// ReadyObj( document ).trigger( "ready" ).unbind( "ready" );
//}
}
},
bindReady: function() {
if ( readyList ) {
return;
}
readyList = ReadyObj._Deferred();
// Catch cases where $(document).ready() is called after the
// browser event has already occurred.
if ( document.readyState === "complete" ) {
// Handle it asynchronously to allow scripts the opportunity to delay ready
return setTimeout( ReadyObj.ready, 1 );
}
// Mozilla, Opera and webkit nightlies currently support this event
if ( document.addEventListener ) {
// Use the handy event callback
document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
// A fallback to window.onload, that will always work
window.addEventListener( "load", ReadyObj.ready, false );
// If IE event model is used
} else if ( document.attachEvent ) {
// ensure firing before onload,
// maybe late but safe also for iframes
document.attachEvent( "onreadystatechange", DOMContentLoaded );
// A fallback to window.onload, that will always work
window.attachEvent( "onload", ReadyObj.ready );
// If IE and not a frame
// continually check to see if the document is ready
var toplevel = false;
try {
toplevel = window.frameElement == null;
} catch(e) {}
if ( document.documentElement.doScroll && toplevel ) {
doScrollCheck();
}
}
},
_Deferred: function() {
var // callbacks list
callbacks = [],
// stored [ context , args ]
fired,
// to avoid firing when already doing so
firing,
// flag to know if the deferred has been cancelled
cancelled,
// the deferred itself
deferred = {
// done( f1, f2, ...)
done: function() {
if ( !cancelled ) {
var args = arguments,
i,
length,
elem,
type,
_fired;
if ( fired ) {
_fired = fired;
fired = 0;
}
for ( i = 0, length = args.length; i < length; i++ ) {
elem = args[ i ];
type = ReadyObj.type( elem );
if ( type === "array" ) {
deferred.done.apply( deferred, elem );
} else if ( type === "function" ) {
callbacks.push( elem );
}
}
if ( _fired ) {
deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] );
}
}
return this;
},
// resolve with given context and args
resolveWith: function( context, args ) {
if ( !cancelled && !fired && !firing ) {
// make sure args are available (#8421)
args = args || [];
firing = 1;
try {
while( callbacks[ 0 ] ) {
callbacks.shift().apply( context, args );//shifts a callback, and applies it to document
}
}
finally {
fired = [ context, args ];
firing = 0;
}
}
return this;
},
// resolve with this as context and given arguments
resolve: function() {
deferred.resolveWith( this, arguments );
return this;
},
// Has this deferred been resolved?
isResolved: function() {
return !!( firing || fired );
},
// Cancel
cancel: function() {
cancelled = 1;
callbacks = [];
return this;
}
};
return deferred;
},
type: function( obj ) {
return obj == null ?
String( obj ) :
class2type[ Object.prototype.toString.call(obj) ] || "object";
}
}
// The DOM ready check for Internet Explorer
function doScrollCheck() {
if ( ReadyObj.isReady ) {
return;
}
try {
// If IE is used, use the trick by Diego Perini
// http://javascript.nwbox.com/IEContentLoaded/
document.documentElement.doScroll("left");
} catch(e) {
setTimeout( doScrollCheck, 1 );
return;
}
// and execute any waiting functions
ReadyObj.ready();
}
// Cleanup functions for the document ready method
if ( document.addEventListener ) {
DOMContentLoaded = function() {
document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
ReadyObj.ready();
};
} else if ( document.attachEvent ) {
DOMContentLoaded = function() {
// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
if ( document.readyState === "complete" ) {
document.detachEvent( "onreadystatechange", DOMContentLoaded );
ReadyObj.ready();
}
};
}
function ready( fn ) {
// Attach the listeners
ReadyObj.bindReady();
var type = ReadyObj.type( fn );
// Add the callback
readyList.done( fn );//readyList is result of _Deferred()
}
return ready;
})();
Как пользоваться:
<script>
ready(function(){
alert('It works!');
});
ready(function(){
alert('Also works!');
});
</script>
Я не уверен, насколько функционален этот код, но он отлично работал с моими поверхностными тестами. Это заняло довольно много времени, поэтому я надеюсь, что вы и другие можете извлечь из этого пользу.
PS: предлагаю компилировать.
Или вы можете использовать http://dustindiaz.com/smallest-domready-ever:
function r(f){/in/.test(document.readyState)?setTimeout(r,9,f):f()}
r(function(){/*code to run*/});
или нативную функцию, если вам нужно только поддерживать новые браузеры (в отличие от готового jQuery, он не запустится, если вы добавите его после загрузки страницы)
document.addEventListener('DOMContentLoaded',function(){/*fun code to run*/})
Ответ 3
Три варианта:
- Если
script
- последний тег тела, DOM будет готов до выполнения тега script
- Когда DOM готов, "readyState" изменится на "complete"
- Поместите все под прослушиватель событий "DOMContentLoaded"
onreadystatechange
document.onreadystatechange = function () {
if (document.readyState == "complete") {
// document is ready. Do your stuff here
}
}
Источник: MDN
DOMContentLoaded
document.addEventListener('DOMContentLoaded', function() {
console.log('document is ready. I can sleep now');
});
Обеспокоенный браузерами каменного века:
Перейдите в исходный код jQuery и используйте функцию ready
. В этом случае вы не разбираетесь и не выполняете всю библиотеку, которую вы делаете, только очень маленькую ее часть.
Ответ 4
Поместите свой <script>/*JavaScript code*/</script>
вправо перед закрывающим тегом </body>
.
По общему признанию, это может не устраивать все цели, поскольку для изменения файла HTML требуется просто изменить файл HTML, а не просто что-то сделать в файле JavaScript a la document.ready
, но все же...
Ответ 5
Бедственное решение:
var checkLoad = function() {
document.readyState !== "complete" ? setTimeout(checkLoad, 11) : alert("loaded!");
};
checkLoad();
Просмотр скрипта
Добавлено это, немного лучше, я думаю, собственный объем и не рекурсивный
(function(){
var tId = setInterval(function() {
if (document.readyState == "complete") onComplete()
}, 11);
function onComplete(){
clearInterval(tId);
alert("loaded!");
};
})()
View Fiddle
Ответ 6
Я использую это:
document.addEventListener("DOMContentLoaded", function(event) {
//Do work
});
Примечание. Вероятно, это работает только с более новыми браузерами, особенно такими: http://caniuse.com/#feat=domcontentloaded
Ответ 7
Действительно, если вас беспокоит Internet 9+, этого кода было бы достаточно, чтобы заменить jQuery.ready
:
document.addEventListener("DOMContentLoaded", callback);
Если вы беспокоитесь о Internet Explorer 6 и некоторых действительно странных и редких браузерах, это будет работать:
domReady: function (callback) {
// Mozilla, Opera and WebKit
if (document.addEventListener) {
document.addEventListener("DOMContentLoaded", callback, false);
// If Internet Explorer, the event model is used
} else if (document.attachEvent) {
document.attachEvent("onreadystatechange", function() {
if (document.readyState === "complete" ) {
callback();
}
});
// A fallback to window.onload, that will always work
} else {
var oldOnload = window.onload;
window.onload = function () {
oldOnload && oldOnload();
callback();
}
}
},
Ответ 8
Этот вопрос задавался довольно давно. Для любого, кто только видит этот вопрос, теперь есть сайт под названием "вам может не понадобиться jquery" , который разбивается - по уровню поддержки IE требуется - все функции jquery и предоставляет некоторые альтернативные, более мелкие библиотеки.
Документ IE8 готов script в соответствии с вам может не понадобиться jquery
function ready(fn) {
if (document.readyState != 'loading')
fn();
else if (document.addEventListener)
document.addEventListener('DOMContentLoaded', fn);
else
document.attachEvent('onreadystatechange', function() {
if (document.readyState != 'loading')
fn();
});
}
Ответ 9
Недавно я использовал это для мобильного сайта. Это упрощенная версия John Resig от "Pro JavaScript Techniques". Это зависит от addEvent.
var ready = ( function () {
function ready( f ) {
if( ready.done ) return f();
if( ready.timer ) {
ready.ready.push(f);
} else {
addEvent( window, "load", isDOMReady );
ready.ready = [ f ];
ready.timer = setInterval(isDOMReady, 13);
}
};
function isDOMReady() {
if( ready.done ) return false;
if( document && document.getElementsByTagName && document.getElementById && document.body ) {
clearInterval( ready.timer );
ready.timer = null;
for( var i = 0; i < ready.ready.length; i++ ) {
ready.ready[i]();
}
ready.ready = null;
ready.done = true;
}
}
return ready;
})();
Ответ 10
Ответ jQuery был очень полезен для меня. С небольшим количеством исправлений он хорошо меня удовлетворил.
Надеюсь, это поможет кому-то еще.
function onReady ( callback ){
var addListener = document.addEventListener || document.attachEvent,
removeListener = document.removeEventListener || document.detachEvent
eventName = document.addEventListener ? "DOMContentLoaded" : "onreadystatechange"
addListener.call(document, eventName, function(){
removeListener( eventName, arguments.callee, false )
callback()
}, false )
}
Ответ 11
Кросс-браузер (тоже старые браузеры) и простое решение:
var docLoaded = setInterval(function () {
if(document.readyState !== "complete") return;
clearInterval(docLoaded);
/*
Your code goes here i.e. init()
*/
}, 30);
Отображение оповещения в jsfiddle
Ответ 12
Вот наименьший фрагмент кода для проверки готовности DOM, который работает во всех браузерах (даже IE 8):
r(function(){
alert('DOM Ready!');
});
function r(f){/in/.test(document.readyState)?setTimeout('r('+f+')',9):f()}
Смотрите ответ.
Ответ 13
Просто добавьте это в нижнюю часть своей HTML-страницы...
<script>
Your_Function();
</script>
Потому что HTML-документы анализируются верхним дном.
Ответ 14
Стоит посмотреть Rock Solid addEvent() и http://www.braksator.com/how-to-make-your-own-jquery.
Вот код, если сайт идет вниз
function addEvent(obj, type, fn) {
if (obj.addEventListener) {
obj.addEventListener(type, fn, false);
EventCache.add(obj, type, fn);
}
else if (obj.attachEvent) {
obj["e"+type+fn] = fn;
obj[type+fn] = function() { obj["e"+type+fn]( window.event ); }
obj.attachEvent( "on"+type, obj[type+fn] );
EventCache.add(obj, type, fn);
}
else {
obj["on"+type] = obj["e"+type+fn];
}
}
var EventCache = function(){
var listEvents = [];
return {
listEvents : listEvents,
add : function(node, sEventName, fHandler){
listEvents.push(arguments);
},
flush : function(){
var i, item;
for(i = listEvents.length - 1; i >= 0; i = i - 1){
item = listEvents[i];
if(item[0].removeEventListener){
item[0].removeEventListener(item[1], item[2], item[3]);
};
if(item[1].substring(0, 2) != "on"){
item[1] = "on" + item[1];
};
if(item[0].detachEvent){
item[0].detachEvent(item[1], item[2]);
};
item[0][item[1]] = null;
};
}
};
}();
// Usage
addEvent(window, 'unload', EventCache.flush);
addEvent(window, 'load', function(){alert("I'm ready");});
Ответ 15
Этот кросс-браузерный код вызовет функцию после готовности DOM:
var domReady=function(func){
var scriptText='('+func+')();';
var scriptElement=document.createElement('script');
scriptElement.innerText=scriptText;
document.body.appendChild(scriptElement);
};
Вот как это работает:
- Первая строка
domReady
вызывает метод toString
функции, чтобы получить строковое представление функции, которую вы передаете, и обертывает его в выражение, которое сразу вызывает функцию.
- Остальная часть
domReady
создает элемент script с выражением и добавляет его в body
документа.
- Браузер запускает теги script, добавленные к
body
после готовности DOM.
Например, если вы выполните следующее: domReady(function(){alert();});
, к элементу body
добавится следующее:
<script>(function (){alert();})();</script>
Обратите внимание, что это работает только для пользовательских функций. Следующие действия не будут работать: domReady(alert);
Ответ 16
Как насчет этого решения?
// other onload attached earlier
window.onload=function() {
alert('test');
};
tmpPreviousFunction=window.onload ? window.onload : null;
// our onload function
window.onload=function() {
alert('another message');
// execute previous one
if (tmpPreviousFunction) tmpPreviousFunction();
};
Ответ 17
Всегда полезно использовать эквиваленты JavaScript по сравнению с jQuery. Одна из причин - это меньшее количество библиотек, которые зависят от них, и они намного быстрее, чем эквиваленты jQuery.
Одна фантастическая ссылка для эквивалентов jQuery http://youmightnotneedjquery.com/.
Что касается вашего вопроса, я взял приведенный ниже код из приведенной выше ссылки:)
Только оговорка заключается в том, что он работает только с Internet Explorer 9 и более поздней версией.
function ready(fn) {
if (document.readyState != 'loading') {
fn();
}
else {
document.addEventListener('DOMContentLoaded', fn);
}
}
Ответ 18
Мы обнаружили, что наша операционная система имеет очень быструю и кропотливую перекрестную версию, которая может сделать трюк для большинства простых случаев с минимальной реализацией:
window.onReady = function onReady(fn){
document.body ? fn() : setTimeout(function(){ onReady(fn);},50);
};
Ответ 19
Представленные здесь решения setTimeout/setInterval будут работать только в определенных обстоятельствах.
Проблема проявляется особенно в старых версиях Internet Explorer до 8.
Переменные, влияющие на успех этих решений setTimeout/setInterval:
1) dynamic or static HTML
2) cached or non cached requests
3) size of the complete HTML document
4) chunked or non chunked transfer encoding
исходный (собственный Javascript) код, разрешающий эту конкретную проблему, находится здесь:
https://github.com/dperini/ContentLoaded
http://javascript.nwbox.com/ContentLoaded (test)
это код, из которого команда jQuery построила свою реализацию.
Ответ 20
Вот что я использую, это быстро и охватывает все базы, которые я думаю; работает для всего, кроме IE < 9.
(() => { function fn() {
// "On document ready" commands:
console.log(document.readyState);
};
if (document.readyState != 'loading') {fn()}
else {document.addEventListener('DOMContentLoaded', fn)}
})();
Кажется, что это все ломает:
- срабатывает немедленно, если DOM уже готов (если DOM не "загружается", но "интерактивен" или "завершен" )
- Если DOM по-прежнему загружается, он устанавливает прослушиватель событий, когда DOM
доступен (интерактивный).
Событие DOMContentLoaded доступно в IE9 и во всем остальном, поэтому я лично считаю, что это нормально использовать. Перепишите объявление функции стрелки в обычную анонимную функцию, если вы не переписываете свой код с ES2015 на ES5.
Если вы хотите подождать, пока все активы будут загружены, все изображения будут отображаться и т.д., тогда вместо этого используйте window.onload.
Ответ 21
Если вам не нужно поддерживать очень старые браузеры, вот как это сделать, даже если ваш внешний script загружен атрибутом async:
HTMLDocument.prototype.ready = new Promise(function(resolve) {
if(document.readyState != "loading")
resolve();
else
document.addEventListener("DOMContentLoaded", function() {
resolve();
});
});
document.ready.then(function() {
console.log("document.ready");
});
Ответ 22
Я просто использую:
setTimeout(function(){
//reference/manipulate DOM here
});
И в отличие от document.addEventListener("DOMContentLoaded" //etc
, как в самом верхнем ответе, он работает еще в IE9 - http://caniuse.com/#search=DOMContentLoaded указывает только как недавно как IE11.
Например, перейдите в https://netrenderer.com/index.php, выберите Internet Explorer 9 из раскрывающегося списка, введите https://dexygen.github.io/blog/oct-2017/jekyll/jekyll-categories/liquid-templates/2017/10/22/how-jekyll-builds-site-categories.html и нажмите "Render", и вы увидите что-то похожее на скриншот внизу этого сообщения.
См. следующий код Javascript, который я использую в заголовке, чтобы манипулировать стилем темы "Хакер" Jekyll по своему вкусу - в частности, вы можете ссылаться на блок if (location.pathname !== rootPath)
, чтобы увидеть, как я вставляю Home
и Blog Home
, которые отображаются IE9 на сайт NetRenderer.
Интересно, что я наткнулся на это решение setTimeout
в 2009 году: Проверяет готовность переполнения DOM?, который, вероятно, мог быть сформулирован немного лучше, поскольку Я имел в виду использование более сложных подходов к различным инфраструктурам.
setTimeout(function() {//delay execution until after dom is parsed
var containerEls = document.getElementsByClassName('container');
var headingEl = containerEls[0].getElementsByTagName('h1')[0];
var headerEl = document.getElementsByTagName('header')[0];
var downloadsSectionEl = document.getElementById('downloads');
var rootPath = "/";
var blogRootPath = "/blog/";
containerEls[0].style.maxWidth = '800px';
containerEls[1].style.maxWidth = '800px';
headingEl.style.margin = '0';
headerEl.style.marginBottom = '7px';
downloadsSectionEl.style.margin = '0';
if (location.pathname !== rootPath) {
downloadsSectionEl.appendChild(generateNavLink('Home', rootPath));
if (location.pathname !== blogRootPath) {
downloadsSectionEl.appendChild(document.createTextNode(' | '));
downloadsSectionEl.appendChild(generateNavLink('Blog Home', blogRootPath));
}
}
function generateNavLink(linkText, hrefPath) {
var navLink = document.createElement('a');
var linkTextNode = document.createTextNode(linkText);
navLink.setAttribute('href', hrefPath);
navLink.appendChild(linkTextNode);
return navLink;
}
});
![dexygen.github.io на IE9]()
Ответ 23
Готовая функция в jQuery
делает несколько вещей. Честно говоря, я не вижу, чтобы это заменило его, если у вас не было удивительно небольшой выход с вашего сайта. jQuery
- довольно маленькая библиотека, и она обрабатывает все виды кросс-браузера, которые вам понадобятся позже.
Во всяком случае, здесь мало смысла публиковать его, просто откройте jQuery
и посмотрите на метод bindReady
.
Он начинается с вызова либо document.addEventListener("DOMContentLoaded")
либо document.attachEvent('onreadystatechange')
зависимости от модели события и продолжается оттуда.
Ответ 24
Если вы загружаете jQuery в нижней части BODY, но возникают проблемы с кодом, который записывает jQuery (<func> ) или jQuery (document).ready(<func> ), проверьте jqShim в Github.
Вместо того, чтобы воссоздать свою собственную функцию готовности документа, она просто удерживает функции до тех пор, пока не будет доступна jQuery, а затем продолжит работу с jQuery, как ожидалось. Точка перемещения jQuery в нижней части тела - ускорить загрузку страницы, и вы все равно можете выполнить ее, вставив jqShim.min.js в начало вашего шаблона.
Я закончил тем, что написал этот код, чтобы переместить все сценарии в WordPress в нижний колонтитул, и именно этот код прокладки теперь находится прямо в заголовке.
Ответ 25
Для IE9 +:
function ready(fn) {
if (document.readyState != 'loading'){
fn();
} else {
document.addEventListener('DOMContentLoaded', fn);
}
}
Ответ 26
Этот подход является самым коротким способом, о котором я могу думать.
Решение, основанное на событии DOMContentLoaded, работает только в том случае, если перед документом загружается script, тогда как предложенная здесь ленивая проверка гарантирует, что код выполняется всегда, даже в сценариях, загружаемых динамически позже, точно так же, как документ JQuery готов.
Этот код совместим со всеми браузерами (включая некоторые устаревшие, вплоть до IE6 и Safari для Windows).
(function ready() {
if (!document.body) {setTimeout(ready, 50); return;}
// Document is ready here
})();
Ответ 27
function onDocReady(fn){
$d.readyState!=="loading" ? fn():document.addEventListener('DOMContentLoaded',fn);
}
function onWinLoad(fn){
$d.readyState==="complete") ? fn(): window.addEventListener('load',fn);
}
onDocReady обеспечивает обратный вызов, когда HTML dom готов к полному доступу/анализу/манипуляции.
onWinLoad обеспечивает обратный вызов, когда все загружено (изображения и т.д.),
- Эти функции можно вызвать, когда захотите.
- Поддерживает несколько "слушателей".
- Будет работать в любом браузере.
Ответ 28
Попробуй это:
function ready(callback){
if(typeof callback === "function"){
document.addEventListener("DOMContentLoaded", callback);
window.addEventListener("load", callback);
}else{
throw new Error("Sorry, I can not run this!");
}
}
ready(function(){
console.log("It worked!");
});
Ответ 29
Большинство ванильных функций JS Ready НЕ учитывают сценарий, в котором DOMContentLoaded
обработчик DOMContentLoaded
после того, как документ уже загружен. Это означает, что функция никогда не будет работать. Это может произойти, если вы ищете DOMContentLoaded
в async
внешнем скрипте (<script async src="file.js"></script>
).
Приведенный ниже код проверяет наличие DOMContentLoaded
только в том случае, если документ readyState
еще не является interactive
или complete
.
var DOMReady = function(callback) {
document.readyState === "interactive" || document.readyState === "complete" ? callback() : document.addEventListener("DOMContentLoaded", callback());
};
DOMReady(function() {
//DOM ready!
});
Если вы хотите поддержать IE, а также:
var DOMReady = function(callback) {
if (document.readyState === "interactive" || document.readyState === "complete") {
callback();
} else if (document.addEventListener) {
document.addEventListener('DOMContentLoaded', callback());
} else if (document.attachEvent) {
document.attachEvent('onreadystatechange', function() {
if (document.readyState != 'loading') {
callback();
}
});
}
};
DOMReady(function() {
// DOM ready!
});
Ответ 30
Самый минимальный и 100% работающий
Я выбрал ответ от PlainJS, и он отлично работает для меня. Он расширяет DOMContentLoaded
, так что он может быть принят во всех браузерах.
Эта функция является эквивалентом метода jQuery $(document).ready()
:
document.addEventListener('DOMContentLoaded', function(){
// do something
});
Однако, в отличие от jQuery, этот код будет правильно работать только в современных браузерах (IE> 8) и не будет работать в случае, если документ уже отображается на момент вставки этого скрипта (например, через Ajax). Поэтому нам нужно немного расширить это:
function run() {
// do something
}
// in case the document is already rendered
if (document.readyState!='loading') run();
// modern browsers
else if (document.addEventListener)
document.addEventListener('DOMContentLoaded', run);
// IE <= 8
else document.attachEvent('onreadystatechange', function(){
if (document.readyState=='complete') run();
});
Это охватывает практически все возможности и является жизнеспособной заменой помощнику jQuery.