jQueryの$ .ready()に相当する純粋なJavaScript-ページ/ DOMの準備ができたときに関数を呼び出す方法[重複]

1491
chris 2012-03-28 13:57.

jQueryを使用すると、すばらしい.ready()機能を誰もが知っています。

$('document').ready(function(){});

ただし、ライブラリをサポートせずに標準のJavaScriptで記述された関数を実行し、ページで関数を処理する準備ができたらすぐに関数を起動したいとします。これにアプローチする適切な方法は何ですか?

私は私ができることを知っています:

window.onload="myFunction()";

または、bodyタグを使用できます。

<body onload="myFunction()">

または、すべての後にページの下部で試すこともできますが、終了bodyまたはhtmlタグは次のようになります。

<script type="text/javascript">
    myFunction();
</script>

jQueryのような方法で1つ以上の関数を発行するクロスブラウザー(古い/新しい)準拠の方法とは$.ready()何ですか?

10 answers

2124
jfriend00 2012-03-28 14:46.

ブラウザー間の互換性をすべて実行するフレームワークがない場合に行う最も簡単なことは、本文の最後にコードを呼び出すことです。これは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のすべてのバージョン)の場合$(document).ready()、どこからでも(呼び出しスクリプトの位置を気にせずに)呼び出すことができるjQueryのようなメソッドを実装できるようにしたい場合は、次のようなものを使用できます。

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が何をするのかを少し理解するために(スクリプトタグが配置されている場所ならどこでも機能します)。

サポートされている場合は、標準を試します。

document.addEventListener('DOMContentLoaded', fn, false);

フォールバックあり:

window.addEventListener('load', fn, false )

またはIEの古いバージョンの場合、以下を使用します。

document.attachEvent("onreadystatechange", fn);

フォールバックあり:

window.attachEvent("onload", fn);

また、IEコードパスには、私が完全には従わない回避策がいくつかありますが、フレームと関係があるようです。


.ready()プレーンなJavaScriptで記述されたjQueryの完全な代替品は次のとおりです。

(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/


仕組みの概要は次のとおりです。

  1. 非公開の状態変数を使用できるように、IIFE(即時呼び出し関数式)を作成します。
  2. パブリック関数を宣言する docReady(fn, context)
  3. ときにdocReady(fn, context)呼ばれる準備ができてハンドラがすでに解雇している場合は、確認してください。その場合は、JSのこのスレッドがsetTimeout(fn, 1)。で終了した直後に起動するように新しく追加されたコールバックをスケジュールするだけです。
  4. レディハンドラーがまだ起動されていない場合は、後で呼び出すコールバックのリストにこの新しいコールバックを追加します。
  5. ドキュメントの準備ができているかどうかを確認します。その場合は、すべての準備完了ハンドラーを実行します。
  6. ドキュメントの準備ができたときにイベントリスナーをまだインストールしていない場合は、今すぐインストールしてください。
  7. document.addEventListener存在する場合は、.addEventListener()for"DOMContentLoaded""load"eventsの両方を使用してイベントハンドラーをインストールします。「ロード」は安全のためのバックアップイベントであり、必要ありません。
  8. document.addEventListener存在しない場合は、.attachEvent()for"onreadystatechange"および"onload"eventsを使用してイベントハンドラーをインストールします。
  9. onreadystatechangeイベントが発生した場合は、を確認しdocument.readyState === "complete"、そうである場合は、関数を呼び出してすべての準備完了ハンドラーを起動します。
  10. 他のすべてのイベントハンドラーでは、関数を呼び出してすべての準備完了ハンドラーを起動します。
  11. すべてのreadyハンドラーを呼び出す関数で、状態変数をチェックして、すでに起動されているかどうかを確認します。持っている場合は、何もしません。まだ呼び出されていない場合は、ready関数の配列をループして、追加された順序で各関数を呼び出します。これらがすべて呼び出されたことを示すフラグを設定して、2回以上実行されないようにします。
  12. 関数配列をクリアして、使用している可能性のあるクロージャを解放できるようにします。

に登録されたハンドラーは、登録さdocReady()れた順序で解雇されることが保証されています。

docReady(fn)ドキュメントの準備ができた後で呼び出すと、コールバックは、を使用して現在の実行スレッドが完了するとすぐに実行されるようにスケジュールされsetTimeout(fn, 1)ます。これにより、呼び出し元のコードは、JSの現在のスレッドが終了するとすぐに後で呼び出され、呼び出し順序が保持されている場合でも、後で呼び出される非同期コールバックであると常に想定できます。

171
Ram Patra 2015-05-19 21:58.

ここでは、すべてのブラウザーで機能する純粋な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!');
});

ここでの秘訣は、元の作成者が説明したように、document.readyStateプロパティをチェックしていることです。文字列が含まれている場合inuninitializedおよびのように、5loadingつのうち最初の2つのDOM準備完了状態)、タイムアウトを設定して再度確認します。それ以外の場合は、渡された関数を実行します。

そして、これがすべてのブラウザ機能するトリックのjsFiddleです

これを彼らの本に含めてくれたTutorialzineに感謝します。

171
Tom Stickel 2015-07-02 10:31.

jQueryを使用せずにVANILLAプレーンJavaScriptを実行している場合は、次を使用する必要があります(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と書くこともできます。これは、readyが発生した後に実行されるjQueryです。

$(function() {
    console.log("ready!");
});

以下と混同しないでください(これはDOM対応を意味するものではありません):

自己実行型のこのようなIIFEを使用しないでください。

 Example:

(function() {
   // Your page initialization code here  - WRONG
   // The DOM will be available here   - WRONG
})();

このIIFEは、DOMがロードされるのを待ちません。(私はChromeブラウザの最新バージョンについても話している!)

80
PhilT 2012-11-20 05:24.

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/

更新-再利用可能なバージョン

私はちょうど以下を開発しました。これは、下位互換性のない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の非同期読み込みを処理するように作成されていますが、縮小しない限り、最初にこのスクリプトを同期読み込みすることをお勧めします。開発に役立つと思いました。

最新のブラウザは、スクリプトの非同期読み込みもサポートしているため、エクスペリエンスがさらに向上します。非同期のサポートは、ページのレンダリング中に複数のスクリプトを同時にダウンロードできることを意味します。非同期で読み込まれる他のスクリプトに依存する場合や、依存関係を処理するためにミニファイアなどを使用する場合は注意が必要です。

24
Lorcan O'Neill 2015-06-11 03:27.

HubSpotの優秀な人々は、jQueryの優れた点を数多く実現するための純粋なJavascript手法を見つけることができるリソースを持っています。 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'); });
11
Zak The Hat 2016-06-19 20:03.

あなたが何を求めているのかよくわかりませんが、おそらくこれが役立つでしょう:

window.onload = function(){
    // Code. . .

}

または:

window.onload = main;

function main(){
    // Code. . .

}
8
Kernel James 2012-03-28 14:46.

あなたのメソッド(終了bodyタグの前にスクリプトを配置する)

<script>
   myFunction()
</script>
</body>
</html>

新旧のブラウザをサポートするための信頼できる方法です。

6
Vitim.us 2015-11-24 19:15.

準備ができました

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 +

3
rogerdpack 2016-10-29 07:52.

これは、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の準備ができているかどうかを確認する方法も参照してください

2
maxhud 2012-03-28 14:04.

document.ondomcontentready=function(){} トリックを行う必要がありますが、ブラウザとの完全な互換性はありません。

jQueryminを使用する必要があるようです

Related questions

MORE COOL STUFF

ケイト・ブランシェットは3日間一緒に夫と一緒に寝て、25年経ってもまだ夫と結婚しています

ケイト・ブランシェットは3日間一緒に夫と一緒に寝て、25年経ってもまだ夫と結婚しています

ケイト・ブランシェットは、夫に会ったとき、典型的な交際のアドバイスに逆らいました。

マイケルシーンが非営利の俳優である理由

マイケルシーンが非営利の俳優である理由

マイケルシーンは非営利の俳優ですが、それは正確にはどういう意味ですか?

ホールマークスターのコリンエッグレスフィールドがRomaDramaLiveでスリル満点のファンと出会う![エクスクルーシブ]

ホールマークスターのコリンエッグレスフィールドがRomaDramaLiveでスリル満点のファンと出会う![エクスクルーシブ]

特徴的なスターのコリン・エッグレスフィールドは、RomaDrama Liveでのスリル満点のファンとの出会いについて料理しました!加えて、大会での彼のINSPIREプログラム。

「たどりつけば」をオンラインでストリーミングできない理由

「たどりつけば」をオンラインでストリーミングできない理由

ノーザンエクスポージャーが90年代の最も人気のある番組の1つになった理由を確認するには、Blu-rayまたはDVDプレーヤーをほこりで払う必要があります。

バイオニック読書はあなたをより速く読むことができますか?

バイオニック読書はあなたをより速く読むことができますか?

BionicReadingアプリの人気が爆発的に高まっています。しかし、それは本当にあなたを速読術にすることができますか?

ドミニカのボイリング湖:アクセスは簡単ではありませんが、ハイキングする価値があります

ドミニカのボイリング湖:アクセスは簡単ではありませんが、ハイキングする価値があります

ドミニカのボイリング湖は、世界で2番目に大きいボイリング湖です。そこにたどり着くまでのトレッキングは大変で長いですが、努力する価値は十分にあります。

私たちの水をきれいに保つのを助けるためにあなたの髪を寄付してください

私たちの水をきれいに保つのを助けるためにあなたの髪を寄付してください

サロンからのヘアトリミングや個人的な寄付は、油流出を吸収して環境を保護するのに役立つマットとして再利用できます。

ホワイトハウスの最も記憶に残る結婚式を見てください

ホワイトハウスの最も記憶に残る結婚式を見てください

過去200年以上の間にホワイトハウスで結婚したのはほんの数人です。彼らは誰でしたか、そしてそこで結婚式を獲得するために何が必要ですか?

驚くほど素晴らしいDropMixミュージックミキシングカードゲームは30ドルで驚くべき取引です

驚くほど素晴らしいDropMixミュージックミキシングカードゲームは30ドルで驚くべき取引です

DropMixはNFC対応のカードゲームで、基本的にはリミックスアーティストになります。現在、Amazonでは$ 30まで下がっており、これまでで最高の価格に匹敵します。ロックバンドで有名なHarmonixによって開発されたDropMixは、おそらく少し野心的すぎるように思われます。結局のところ、ほとんどの人は素晴らしいリズムを持っていませんが、ゲームは驚くほどうまく実行されます。

メアリーJ.ブライジがついにハリウッドウォークオブフェイムスターを獲得

メアリーJ.ブライジがついにハリウッドウォークオブフェイムスターを獲得

写真:APメアリーJ.ブライジは、間もなくハリウッドウォークオブフェイムのスターを獲得します。これは、メアリーJよりもハリウッドウォークオブフェイムのほうが正直なところ恩恵です。

MeltdownとSpectreの脆弱性についてこれまでに知っていることはすべて、簡単な方法で説明されています

MeltdownとSpectreの脆弱性についてこれまでに知っていることはすべて、簡単な方法で説明されています

画像:グラズ工科大学/ NataschaEiblがデザインしたロゴ。MeltdownとSpectreは、攻撃者がシステムメモリに保存されているあらゆる種類の情報にアクセスできるようにする2つの脆弱性に付けられた名前です。

彼のニューヨークの家から追い出されようとしている97歳の第二次世界大戦の獣医。メリーエフィングクリスマス

彼のニューヨークの家から追い出されようとしている97歳の第二次世界大戦の獣医。メリーエフィングクリスマス

日本人に襲われたときに真珠湾にいた97歳の第二次世界大戦のベテランが、ニューヨークのブルックリンから追い出されています。

Zendaya Wishes Boyfriend Tom Holland Happy Birthday with Cuddly Photo: He 'Makes Me the Happiest'

Zendaya Wishes Boyfriend Tom Holland Happy Birthday with Cuddly Photo: He 'Makes Me the Happiest'

Zendaya shared a sweet photo in honor of boyfriend Tom Holland's 26th birthday Wednesday

小さな女性:脳卒中を患った後に病院から解放されたアトランタのジューシーな赤ちゃん:「まだ癒し」

小さな女性:脳卒中を患った後に病院から解放されたアトランタのジューシーな赤ちゃん:「まだ癒し」

シーレン「Ms.JuicyBaby」ピアソンは、先月脳卒中で入院した後、「もう一度たくさんのことをする方法を学ばなければならない」ため、言語療法を受けていることを明らかにしました。

エマストーンは彼女のクリフサイドマリブビーチハウスを420万ドルでリストアップしています—中を見てください!

エマストーンは彼女のクリフサイドマリブビーチハウスを420万ドルでリストアップしています—中を見てください!

オスカー受賞者の世紀半ばの家には、3つのベッドルーム、2つのバス、オーシャンフロントの景色があります。

ジーニー・メイ・ジェンキンスは、母乳育児の経験の中で、彼女は「本当に、本当に落ち込んでいる」と言います

ジーニー・メイ・ジェンキンスは、母乳育児の経験の中で、彼女は「本当に、本当に落ち込んでいる」と言います

ジーニー・メイ・ジェンキンスは、生後4か月の娘、モナコに母乳育児をしていると語った。

投資ノート:Bioscout AU$300万シード

投資ノート:Bioscout AU$300万シード

Bioscoutは、農家を運転席に置くという使命を負っています。Artesian(GrainInnovate)やUniseedと並んで、最新のシードラウンドでチームを支援できることをうれしく思います。問題真菌症による重大な作物の損失は、農民にとって試練であることが証明されています。

リトルマーケットリサーチ1| 2022年のクイックグリンプス遠隔医療市場

リトルマーケットリサーチ1| 2022年のクイックグリンプス遠隔医療市場

遠隔医療は、パンデミック後の時代では新しいものではなく、時代遅れの分野でもありません。しかし、業界を詳しく見ると、需要と供給の強力な持続可能性と、米国で絶え間ない革命となる強力な潜在的成長曲線を示しています。

スタートアップ資金調達環境:タイのスタートアップエコシステムの次は何ですか?

スタートアップ資金調達環境:タイのスタートアップエコシステムの次は何ですか?

2021年は、世界的なベンチャーキャピタル(VC)の資金調達にとって記録的な年でした。DealStreetAsiaによると、東南アジアも例外ではなく、この地域では年間で記録的な25の新しいユニコーンが採掘されました。

ムーアの法則を超えて

ムーアの法則を超えて

計算に対する私たちの欲求とムーアの法則が提供できるものとの間には、指数関数的に増大するギャップがあります。私たちの文明は計算に基づいています—建築と想像力の現在の限界を超える技術を見つけなければなりません。

Language