Ладно, возможно, это просто глупый вопрос, хотя я уверен, что множество других людей время от времени задают такой же вопрос. Я просто хочу быть уверенным на 100% в любом случае. С jQuery мы все знаем замечательную
$('document').ready(function(){});
Однако, допустим, я хочу запустить функцию, написанную на стандартном JavaScript без какой-либо библиотеки, и что я хочу запустить функцию, как только страница будет готова ее обработать. Как правильно к этому подойти?
Я знаю, что я могу сделать:
window.onload="myFunction()";
...или я могу использовать тег body
:
<body onload="myFunction()">
...или я могу даже попробовать внизу страницы после всего, но в конце body
или html
тега, например:
<script type="text/javascript">
myFunction();
</script>
Каков кроссбраузерный (старый/новый) совместимый метод выдачи одной или нескольких функций подобно jQuery's $.ready()
?
Самое простое, что можно сделать в отсутствие фреймворка, который делает всю кроссбраузерную совместимость за вас, это просто поместить вызов вашего кода в конец тела. Это выполняется быстрее, чем обработчик onload
, потому что он ждет только готовности DOM, а не загрузки всех изображений. И это работает в любом браузере.
<!doctype html>
<html>
<head>
</head>
<body>
Your HTML here
<script>
// self executing function here
(function() {
// your page initialization code here
// the DOM will be available here
})();
</script>
</body>
</html>
Для современных браузеров (начиная с IE9 и новее и любой версии Chrome, Firefox или Safari), если вы хотите иметь возможность реализовать метод jQuery типа $(document).ready()
, который вы можете вызвать из любого места (не беспокоясь о том, где расположен вызывающий скрипт), вы можете просто использовать что-то вроде этого:
function docReady(fn) {
// see if DOM is already available
if (document.readyState === "complete" || document.readyState === "interactive") {
// call on next available tick
setTimeout(fn, 1);
} else {
document.addEventListener("DOMContentLoaded", fn);
}
}
Использование:
docReady(function() {
// DOM is loaded and ready for manipulation here
});
Если вам нужна полная кросс-браузерная совместимость (включая старые версии IE) и вы не хотите ждать window.onload
, то вам, вероятно, стоит посмотреть, как фреймворк вроде jQuery реализует свой метод $(document).ready()
. Это довольно сложно, в зависимости от возможностей браузера.
Чтобы дать вам небольшое представление о том, что делает jQuery (это будет работать везде, где размещен тег script).
Если поддерживается, он пробует стандартный метод:
document.addEventListener('DOMContentLoaded', fn, false);
с отступлением на:
window.addEventListener('load', fn, false )
или для старых версий IE используется:
document.attachEvent("onreadystatechange", fn);
с возможностью возврата к:
window.attachEvent("onload", fn);
И, есть некоторые обходные пути в коде IE, которые я не совсем понимаю, но похоже, что это как-то связано с фреймами.
Вот полная замена jQuery's .ready()
, написанная на обычном javascript:
(function(funcName, baseObj) {
// The public function name defaults to window.docReady
// but you can pass in your own object and own function name and those will be used
// if you want to put them in a different namespace
funcName = funcName || "docReady";
baseObj = baseObj || window;
var readyList = [];
var readyFired = false;
var readyEventHandlersInstalled = false;
// call this when the document is ready
// this function protects itself against being called more than once
function ready() {
if (!readyFired) {
// this must be set to true before we start calling callbacks
readyFired = true;
for (var i = 0; i < readyList.length; i++) {
// if a callback here happens to add new ready handlers,
// the docReady() function will see that it already fired
// and will schedule the callback to run right after
// this event loop finishes so all handlers will still execute
// in order and no new ones will be added to the readyList
// while we are processing the list
readyList[i].fn.call(window, readyList[i].ctx);
}
// allow any closures held by these functions to free
readyList = [];
}
}
function readyStateChange() {
if ( document.readyState === "complete" ) {
ready();
}
}
// This is the one public interface
// docReady(fn, context);
// the context argument is optional - if present, it will be passed
// as an argument to the callback
baseObj[funcName] = function(callback, context) {
if (typeof callback !== "function") {
throw new TypeError("callback for docReady(fn) must be a function");
}
// if ready has already fired, then just schedule the callback
// to fire asynchronously, but right away
if (readyFired) {
setTimeout(function() {callback(context);}, 1);
return;
} else {
// add the function and context to the list
readyList.push({fn: callback, ctx: context});
}
// if document already ready to go, schedule the ready function to run
if (document.readyState === "complete") {
setTimeout(ready, 1);
} else if (!readyEventHandlersInstalled) {
// otherwise if we don't have event handlers installed, install them
if (document.addEventListener) {
// first choice is DOMContentLoaded event
document.addEventListener("DOMContentLoaded", ready, false);
// backup is window load event
window.addEventListener("load", ready, false);
} else {
// must be IE
document.attachEvent("onreadystatechange", readyStateChange);
window.attachEvent("onload", ready);
}
readyEventHandlersInstalled = true;
}
}
})("docReady", window);
Последняя версия кода находится в открытом доступе на GitHub по адресу https://github.com/jfriend00/docReady.
Использование:
// pass a function reference
docReady(fn);
// use an anonymous function
docReady(function() {
// code here
});
// pass a function reference and a context
// the context will be passed to the function as the first argument
docReady(fn, context);
// use an anonymous function with a context
docReady(function(context) {
// code here that can use the context argument that was passed to docReady
}, ctx);
Это было протестировано в:
IE6 and up
Firefox 3.6 and up
Chrome 14 and up
Safari 5.1 and up
Opera 11.6 and up
Multiple iOS devices
Multiple Android devices
Рабочая реализация и тестовый стенд:
Вот краткое описание того, как это работает:
docReady(fn, context)
.docReady(fn, context)
, проверяем, сработал ли уже обработчик готовности. Если да, просто запланируйте новый добавленный обратный вызов сразу после завершения этого потока JS с помощью setTimeout(fn, 1)
.document.addEventListener
существует, то установите обработчики событий с помощью .addEventListener()
для событий "DOMContentLoaded"
и "load"
. Событие "load" является резервным событием для безопасности и не должно быть необходимым.document.addEventListener
не существует, то установите обработчики событий с помощью .attachEvent()
для событий "onreadystatechange"
и "onload"
.onreadystatechange
проверьте, является ли document.readyState === "complete"
и если да, вызовите функцию для запуска всех обработчиков готовности.Обработчики, зарегистрированные с помощью docReady()
, гарантированно будут запущены в том порядке, в котором они были зарегистрированы.
Если вы вызываете docReady(fn)
после того, как документ уже готов, обратный вызов будет запланирован на выполнение, как только текущий поток выполнения завершится с помощью setTimeout(fn, 1)
. Это позволяет вызывающему коду всегда считать, что это асинхронные обратные вызовы, которые будут вызваны позже, даже если позже - это как только завершится текущий поток JS, и сохраняет порядок вызовов.
Я хотел бы упомянуть некоторые из возможных путей здесь вместе с чистого JavaScript трюк, который работает во всех браузерах:
// with jQuery
$(document).ready(function(){ /* ... */ });
// shorter jQuery version
$(function(){ /* ... */ });
// without jQuery (doesn't work in older IEs)
document.addEventListener('DOMContentLoaded', function(){
// your code goes here
}, false);
// and here's the trick (works everywhere)
function r(f){/in/.test(document.readyState)?setTimeout('r('+f+')',9):f()}
// use like
r(function(){
alert('DOM Ready!');
});
Хитрость здесь, как пояснил автор, заключается в том, что мы проверяем, документ.в свойстве readyState собственность. Если он содержит строку в
(как в не инициализирована
и загрузки
, первые два дом готов Штатов из 5) мы устанавливаем таймаут и снова проверить. В противном случае, мы выполняем переданную функцию.
И здесь'ы [jsFiddle][3] для трюк, который работает во всех браузерах.
Спасибо Tutorialzine для включения в свою книгу.
Если вы делаете ваниль обычная язык JavaScript без jQuery, то вы должны использовать (интернет&ампер;усилитель; nbsp;Обозреватель&ампер;усилитель; nbsp;9 или более поздней версии):
document.addEventListener("DOMContentLoaded", function(event) {
// Your code to run since DOM is loaded and ready
});
Выше эквивалент в jQuery .готов
:
$(document).ready(function() {
console.log("Ready!");
});
Которые также могут быть написаны сокращенное такой, что jQuery будет работать после готов даже возникает.
$(function() {
console.log("ready!");
});
Не путать с ниже (которая не претендует на дом готовы):
Не используйте жизнь такой, что имеет самостоятельного выполнения:
Example:
(function() {
// Your page initialization code here - WRONG
// The DOM will be available here - WRONG
})();
Эта жизнь не будет ждать для Ваш дом, чтобы загрузить. (Я'м даже не говорю о последней версии браузера Хром!)
Испытания в IE9, и последний Firefox и Chrome, а также поддерживается в IE8.
document.onreadystatechange = function () {
var state = document.readyState;
if (state == 'interactive') {
init();
} else if (state == 'complete') {
initOnCompleteLoad();
}
};
Пример:
Обновление - многоразовые версия
Я просто развил следующее. Это'ы довольно упрощенный эквивалент в jQuery или дом готов без обратной совместимости. Он, вероятно, нуждается в дальнейшей доработке. Тестирование в последних версиях Chrome, Firefox и IE (10/11) и должны работать в старых браузерах, как прокомментировал. Я'будете обновлять, если я найду какие-либо вопросы.
window.readyHandlers = [];
window.ready = function ready(handler) {
window.readyHandlers.push(handler);
handleState();
};
window.handleState = function handleState () {
if (['interactive', 'complete'].indexOf(document.readyState) > -1) {
while(window.readyHandlers.length > 0) {
(window.readyHandlers.shift())();
}
}
};
document.onreadystatechange = window.handleState;
Использование:
ready(function () {
// your code here
});
Это's написано для обработки асинхронной загрузки JS, но вы, возможно, захотите синхронизация загрузите этот скрипт, если вы не'вновь сокращение. Я'вэ нашел его полезным в развитии.
Современные браузеры также поддерживают асинхронной загрузкой скриптов, которые еще больше усиливает впечатление. Поддержка асинхронных помощью нескольких скриптов можно загрузить одновременно все то же время отрисовки страницы. Просто следите, когда в зависимости от другие скрипты загружаются асинхронно или использовать английское сокращение Cups или что-то вроде browserify, чтобы справиться с зависимостями.
Хорошие люди в HubSpot есть ресурс, где можно найти чисто методологии JavaScript для достижения много jQuery и добра - в том числе и "готово"
http://youmightnotneedjquery.com/#ready
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();
});
}
}
пример рядный использование:
ready(function() { alert('hello'); });
Я'м не совсем уверен, что вы'повторно просить, но, может быть, это может помочь:
window.onload = function(){
// Code. . .
}
Или:
window.onload = main;
function main(){
// Code. . .
}
Ваш метод (размещение скрипта перед закрывающим тегом body)
<script>
myFunction()
</script>
</body>
</html>
это надежный способ поддержки старых и новых браузеров.
function ready(fn){var d=document;(d.readyState=='loading')?d.addEventListener('DOMContentLoaded',fn):fn();}
Использовать как
ready(function(){
//some code
});
(function(fn){var d=document;(d.readyState=='loading')?d.addEventListener('DOMContentLoaded',fn):fn();})(function(){
//Some Code here
//DOM is avaliable
//var h1s = document.querySelector("h1");
});
Поддержка: в IE9+
Здесь'ы очищенную, номера-ивал-через версия ОЗУ-Сваруп'С, что "работает во всех браузерах, что" Выбор-работает во всех браузерах!
function onReady(yourMethod) {
var readyStateCheckInterval = setInterval(function() {
if (document && document.readyState === 'complete') { // Or 'interactive'
clearInterval(readyStateCheckInterval);
yourMethod();
}
}, 10);
}
// use like
onReady(function() { alert('hello'); } );
Это, однако, подождать лишние 10 мс для запуска, так вот's более сложный путь, который должен'т:
function onReady(yourMethod) {
if (document.readyState === 'complete') { // Or also compare to 'interactive'
setTimeout(yourMethod, 1); // Schedule to run immediately
}
else {
readyStateCheckInterval = setInterval(function() {
if (document.readyState === 'complete') { // Or also compare to 'interactive'
clearInterval(readyStateCheckInterval);
yourMethod();
}
}, 10);
}
}
// Use like
onReady(function() { alert('hello'); } );
// Or
onReady(functionName);
Смотрите также https://stackoverflow.com/questions/8100576/how-to-check-if-dom-is-ready-without-a-framework.