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

「水曜日」シーズン1の中心には大きなミステリーがあります

「水曜日」シーズン1の中心には大きなミステリーがあります

Netflixの「水曜日」は、典型的な10代のドラマ以上のものであり、実際、シーズン1にはその中心に大きなミステリーがあります.

ボディーランゲージの専門家は、州訪問中にカミラ・パーカー・ボウルズが輝くことを可能にした微妙なケイト・ミドルトンの動きを指摘しています

ボディーランゲージの専門家は、州訪問中にカミラ・パーカー・ボウルズが輝くことを可能にした微妙なケイト・ミドルトンの動きを指摘しています

ケイト・ミドルトンは、州の夕食会と州の訪問中にカミラ・パーカー・ボウルズからスポットライトを奪いたくなかった、と専門家は言う.

一部のファンがハリー・スタイルズとオリビア・ワイルドの「非常に友好的な」休憩が永続的であることを望んでいる理由

一部のファンがハリー・スタイルズとオリビア・ワイルドの「非常に友好的な」休憩が永続的であることを望んでいる理由

一部のファンが、オリビア・ワイルドが彼女とハリー・スタイルズとの間の「難しい」が「非常に友好的」な分割を恒久的にすることを望んでいる理由を見つけてください.

エリザベス女王の死後、ケイト・ミドルトンはまだ「非常に困難な時期」を過ごしている、と王室の専門家が明らかにする 

エリザベス女王の死後、ケイト・ミドルトンはまだ「非常に困難な時期」を過ごしている、と王室の専門家が明らかにする&nbsp;

エリザベス女王の死後、ケイト・ミドルトンが舞台裏で「非常に困難な時期」を過ごしていたと伝えられている理由を調べてください.

セントヘレナのジェイコブのはしごを登るのは、気弱な人向けではありません

セントヘレナのジェイコブのはしごを登るのは、気弱な人向けではありません

セント ヘレナ島のジェイコブズ ラダーは 699 段の真っ直ぐ上る階段で、頂上に到達すると証明書が発行されるほどの難易度です。

The Secrets of Airline Travel Quiz

The Secrets of Airline Travel Quiz

Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?

Where in the World Are You? Take our GeoGuesser Quiz

Where in the World Are You? Take our GeoGuesser Quiz

The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!

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

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

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

パンデミックは終わったかもしれないが、Covid-19 は終わっていない

パンデミックは終わったかもしれないが、Covid-19 は終わっていない

2021 年 6 月 8 日にニューヨーク市で開催された covid-19 パンデミックで亡くなった人々の命を偲び、祝うために、ネーミング ザ ロスト メモリアルズが主催するイベントと行進の最中に、グリーンウッド墓地の正門から記念碑がぶら下がっています。週末、ジョー・バイデン大統領は、covid-19 パンデミックの終息を宣言しました。これは、過去 2 年以上にわたり、公の場でそうするための長い列の中で最新のものです。

デビル・イン・オハイオの予告編は、エミリー・デシャネルもオハイオにいることを明らかにしています

デビル・イン・オハイオの予告編は、エミリー・デシャネルもオハイオにいることを明らかにしています

オハイオ州のエミリー・デシャネル みんな早く来て、ボーンズが帰ってきた!まあ、ショーボーンズではなく、彼女を演じた俳優. エミリー・デシャネルに最後に会ってからしばらく経ちました.Emily Deschanel は、長期にわたるプロシージャルな Bones の Temperance “Bones” Brennan としてよく知られています。

ドナルド・トランプはFBIのマー・ア・ラーゴ襲撃映像をリリースする予定ですか?

ドナルド・トランプはFBIのマー・ア・ラーゴ襲撃映像をリリースする予定ですか?

どうやら、ドナルド・トランプに近い人々は、今月初めにFBIによって家宅捜索された彼のMar-a-Lago財産からの映像を公開するよう彼に勧めています. 前大統領はテープを公開するかどうかを確認していませんが、息子はフォックス・ニュースにそうなるだろうと語った.

Andor は、他の Star Wars ショーから大きな距離を置きます。

Andor は、他の Star Wars ショーから大きな距離を置きます。

アンドールの一場面。数十年前、ジョージ・ルーカスがスター・ウォーズのテレビ番組を制作するのを妨げた主な理由は、お金でした。

ケイト・ミドルトンとウィリアム王子は、彼らが子供たちと行っているスパイをテーマにした活動を共有しています

ケイト・ミドルトンとウィリアム王子は、彼らが子供たちと行っているスパイをテーマにした活動を共有しています

ケイト・ミドルトンとウィリアム王子は、子供向けのパズルの本の序文を書き、ジョージ王子、シャーロット王女、ルイ王子と一緒にテキストを読むと述べた.

事故で押しつぶされたスイカは、動物を喜ばせ水分補給するために野生生物保護団体に寄付されました

事故で押しつぶされたスイカは、動物を喜ばせ水分補給するために野生生物保護団体に寄付されました

Yak's Produce は、数十個のつぶれたメロンを野生動物のリハビリ専門家であるレスリー グリーンと彼女のルイジアナ州の救助施設で暮らす 42 匹の動物に寄付しました。

デミ・ロヴァートは、新しいミュージシャンのボーイフレンドと「幸せで健康的な関係」にあります: ソース

デミ・ロヴァートは、新しいミュージシャンのボーイフレンドと「幸せで健康的な関係」にあります: ソース

8 枚目のスタジオ アルバムのリリースに向けて準備を進めているデミ ロヴァートは、「スーパー グレート ガイ」と付き合っている、と情報筋は PEOPLE に確認しています。

Plathville の Kim と Olivia Plath が数年ぶりに言葉を交わすことへようこそ

Plathville の Kim と Olivia Plath が数年ぶりに言葉を交わすことへようこそ

イーサン プラスの誕生日のお祝いは、TLC のウェルカム トゥ プラスビルのシーズン 4 のフィナーレで、戦争中の母親のキム プラスと妻のオリビア プラスを結びつけました。

仕事の生産性を高める 8 つのシンプルなホーム オフィスのセットアップのアイデア

仕事の生産性を高める 8 つのシンプルなホーム オフィスのセットアップのアイデア

ホームオフィスのセットアップ術を極めよう!AppExert の開発者は、家族全員が一緒にいる場合でも、在宅勤務の技術を習得しています。祖父や曽祖父が共同家族で暮らしていた頃の記憶がよみがえりました。

2022 年、私たちのデジタル ライフはどこで終わり、「リアル ライフ」はどこから始まるのでしょうか?

20 年前のタイムトラベラーでさえ、日常生活におけるデジタルおよびインターネットベースのサービスの重要性に驚くことでしょう。MySpace、eBay、Napster などのプラットフォームは、高速化に焦点を合わせた世界がどのようなものになるかを示してくれました。

ニューロマーケティングの秘密科学

ニューロマーケティングの秘密科学

マーケティング担当者が人間の欲望を操作するために使用する、最先端の (気味が悪いと言う人もいます) メソッドを探ります。カートをいっぱいにして 3 桁の領収書を持って店を出る前に、ほんの数点の商品を買いに行ったことはありませんか? あなたは一人じゃない。

地理情報システムの日: GIS 開発者として学ぶべき最高の技術スタック

地理情報システムの日: GIS 開発者として学ぶべき最高の技術スタック

私たちが住んでいる世界を確実に理解するには、データが必要です。ただし、空間参照がない場合、このデータは地理的コンテキストがないと役に立たなくなる可能性があります。

Language