Хорошо, это может быть глупый вопрос, хотя я уверен, что есть много других людей, которые задают один и тот же вопрос время от времени. Я, я просто хочу сделать 100% уверенным в этом в любом случае. С jQuery мы все знаем замечательные
$('document').ready(function(){});
Однако, скажем, я хочу запустить функцию, написанную в стандартном JavaScript, без поддержки библиотеки, и что я хочу запустить функцию, как только страница будет готова к ее обработке. Каким образом можно подойти к этому?
Я знаю, что могу:
window.onload="myFunction()";
... или я могу использовать тег body
:
<body onload="myFunction()">
... или я могу даже попробовать в нижней части страницы после всего, но тег конца body
или html
, например:
<script type="text/javascript">
myFunction();
</script>
Что такое кросс-браузерный (старый/новый) -комплексный метод выдачи одной или нескольких функций таким образом, как jQuery $.ready()
?
Простейшая вещь, которую нужно сделать в отсутствие рамки, которая делает всю кросс-браузерную совместимость для вас, - это просто позвонить вашему коду в конце тела. Это выполняется быстрее, чем обработчик onload
, потому что он ожидает только готовности DOM, а не для загрузки всех изображений. И это работает в каждом браузере.
<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>
Если вы действительно не хотите этого делать, и вам нужна кросс-браузерная совместимость, и вы не хотите ждать 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 .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
Рабочая реализация и тестовое постель: http://jsfiddle.net/jfriend00/YfD3C/
Вот краткое описание того, как это работает:
docReady(fn, context)
docReady(fn, context)
, проверьте, уже готов ли готовый обработчик. Если да, просто назначьте вновь добавленный обратный вызов для запуска сразу после того, как этот поток JS заканчивается с помощью setTimeout(fn, 1)
.document.addEventListener
, установите обработчики событий, используя .addEventListener()
для событий "DOMContentLoaded"
и "load"
. "Нагрузка" является резервным событием для безопасности и не требуется.document.addEventListener
не существует, установите обработчики событий, используя .attachEvent()
для "onreadystatechange"
и "onload"
событий.onreadystatechange
проверьте, есть ли document.readyState === "complete"
, и если да, вызовите функцию, чтобы запустить все готовые обработчики.Обработчики, зарегистрированные в docReady()
, должны быть уволены в том порядке, в котором они были зарегистрированы.
Если вы вызываете docReady(fn)
после того, как документ уже готов, обратный вызов будет запланирован для выполнения, как только текущий поток выполнения завершится с помощью setTimeout(fn, 1)
. Это позволяет вызывающему коду всегда предполагать, что они являются асинхронными обратными вызовами, которые будут вызваны позже, даже если позже это произойдет, как только текущий поток JS завершится, и он сохранит порядок вызова.
document.write()
в вашем javascript и простоты, к которой это приводит при кодировании / реализации, весь javascript, который явно не помечен как отложенный или асинхронный, загружается последовательно, как он встречается на странице, и все то есть до того, как оно в файле уже выполнено или проанализировано.
Я хотел бы упомянуть некоторые из возможных способов здесь вместе с трюком чистого 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 the trick (works everywhere)
function r(f){/in/.test(document.readyState)?setTimeout('r('+f+')',9):f()}
// use like
r(function(){
alert('DOM Ready!');
});
Трюк здесь, как объяснил оригинальный автор, заключается в том, что мы проверяем свойство document.readyState, Если он содержит строку in
(как в uninitialized
и loading
, первые два состояния готовности DOM из 5), мы установили тайм-аут и повторить проверку. В противном случае мы выполним переданную функцию.
И здесь jsFiddle для трюка, который работает во всех браузерах.
Благодаря Tutorialzine для включения этого в свою книгу.
Протестировано в IE9, а также последние версии Firefox и Chrome, а также поддерживается в IE8.
document.onreadystatechange = function () {
var state = document.readyState;
if (state == 'interactive') {
init();
} else if (state == 'complete') {
initOnCompleteLoad();
}
};
Пример: http://jsfiddle.net/electricvisions/Jacck/
UPDATE - версия многократного использования
Я только что разработал следующее. Это довольно упрощенный эквивалент jQuery или Dom, готовый без обратной совместимости. Это, вероятно, нуждается в дальнейшей доработке. Протестировано в последних версиях 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
});
Он написан для обработки асинхронной загрузки JS, но вы можете синхронизировать загрузку этого script сначала, если вы не уменьшаете. Я нашел это полезным в разработке.
Современные браузеры также поддерживают асинхронную загрузку скриптов, что еще больше увеличивает опыт. Поддержка async означает, что сразу несколько сценариев могут быть загружены при показе страницы. Просто следите, в зависимости от других сценариев, загружаемых асинхронно, или используйте minifier или что-то вроде браузера для обработки зависимостей.
addEventListener
@rogerdpack? attachEvent
больше не поддерживается ни в одном браузере, но я понимаю вашу точку зрения. Я обновлю.
Если вы используете VANILLA обычный JavaScript без jQuery, то вы должны использовать (Internet Explorer 9 или новее):
document.addEventListener("DOMContentLoaded", function(event) {
// Your code to run since DOM is loaded and ready
});
Выше соответствует эквивалент jQuery .ready
:
$(document).ready(function() {
console.log("Ready!");
});
К какой ТАКЖЕ можно было бы написать SHORTHAND, как это, какой jQuery будет запущен после того, как будет готов даже .
$(function() {
console.log("ready!");
});
НЕ ПОДТВЕРЖДАЕТСЯ НИЖЕ (что не предназначено для готовности DOM):
НЕ используйте IFFI, который выполняется самостоятельно:
Example:
(function() {
// Your page initialization code here - WRONG
// The DOM will be available here - WRONG
})();
Этот IFFI НЕ будет ждать загрузки DOM. (Я даже говорю о последней версии браузера Chrome!)
У хороших людей в HubSpot есть ресурс, где вы можете найти чистые Javascript-методологии для достижения большого успеха jQuery - в том числе ready
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'); });
Ваш метод (размещение script перед тегом закрывающего тела)
<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 +
Я не совсем уверен, что вы спрашиваете, но, может быть, это может помочь:
window.onload = function(){
// Code. . .
}
Или:
window.onload = main;
function main(){
// Code. . .
}
Здесь используется очищенная, неэвалевая версия версии Ram-swaroop "работает во всех браузерах":
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 мс для запуска, поэтому здесь более сложный путь, который не должен:
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);
См. также Как проверить, готова ли DOM без рамки?.
document.ondomcontentready=function(){}
должен сделать трюк, но он не имеет полной совместимости с браузером.
Похоже, вы должны просто использовать jQuery min