動的作成scriptノード

6182 ワード

文章が長いので、本当に必要なのは根気よく読んでください.
たとえば、私たちはa.jsをロードしたいです.普通はこう書きます.
var head = document.getElementsByTagName('head')[0];

var script = document.createElement('script');

script.type = 'text/javascript';

script.src = 'a.js';

head.appendChild(script);

知識のポイントを言って、後から使います.
Operaという商品は徹底的に底の両面派です.例えば、IEのatachEventをサポートします.標準のaddEventListenerもサポートします.これはIEのcurrentStyleをサポートしています.標準のwindow.get ComputatidStyleもサポートしています.一つだけではない. 
だから、時々IEのfixに対して、Operaを排除する必要があります.それはより良い方法を実現した以上、より良い方法を使いたいです.私たちの目的は遅れたIEです.これだけです.
Opera検査技術:var isOpera= typeof opera!='undefined'&opera.toString()=='[object Opera]'
もし私たちはa.jsのfn()のメソッドを呼び出す必要があるならば、この過程は非同期ですので、jsファイルのロードが完了するまで調整できます.ロードが完了したかどうかをどう判断しますか?
var isOpera = typeof opera !== 'undefined' && opera.toString() === '[object Opera]',

    head = document.getElementsByTagName('head')[0],

    script = document.createElement('script');

script.type = 'text/javascript';

if (script.attachEvent && !isOpera) {

    script.attachEvent('readystatechange', onScriptLoad);

} else {

    script.addEventListener('load', onScriptLoad);

}

script.src = 'a.js';

head.appendChild(script);

懸念は引き続きOScript Load方法を残しています.ここにもう一つの知識点を挿入します.readyState、以下の値を含みます.
0:「uninitialized」–元の状態
1:「loading」–ロード中
2:「loaded」–読み込み完了
3:「interactive」–まだ実行されていません.
4:「complette」–スクリプトの実行が完了しました.
なぜ私が「:」と書いたのかというと、xhrでは、要求が完了した時のreadyStateは数字の形で、すなわち「:」の左側の部分がノードでロードされた時、readyStateは文字列の形で、すなわち「:」の右側の部分です.この中での互換性については、PPKを参照してください.
なぜこれを言いますか?もちろんIEのためです.他のブラウザではシナリオの読み込みが完了するとワンロードイベントが発生しますので、問題はありませんが、IEはワンロードとは何かが分かりませんので、独自派です.
Chrome 14をテストしました.Firefox 8、Opera 11、Safari 5、onloadイベントのトリガはシナリオの実行が終わった後で、例えばa.jsをお願いします.このファイルの最後の行にalert('xxx')を書きます.その後、script.onload=function(){alert('onload')}、印刷順序が一致するのはxxx->onloadです.
私はまたscript.addEvent Listenerを試しました.結果は同じです.
IEはオンレadystatechangeイベントをサポートしています.Operaは両方ともサポートしています.同じようにOperaをフィルタリングします.IE 9はどうですか?はい、わかりません.IE 9のaddEventListener方法は他の標準ブラウザとあまり一致しないと聞きました.このIE 9を伝統的なIEブラウザの範疇に入れました.
スクリプトのロードが完了したかどうかをどう判断しますか?一般的なやり方はscript.readyStateを判断します.IEは変態です.この値も固定されていないので、こうしなければなりません.
script.readyState === 'loaded' || script.readyState === 'complete'

ここのロード判定については、いくつかのフレームのデザインを参考にしましたが、RequireJSの他にevent.type=='load'が多く使われていますので、私達もこの文を使って、みんなで死にましょう.
もう一つのポイントがあります.OScript Loadに統一して置いて処理します.標準ブラウザの中でscript.readyStateはundefinedです.メモリ漏れを防止するために、ロードが完了したらscriptノードを削除してコードを参照してください.
function onScriptLoad(e) {

	e = e || window.event;

	var script = e.target || e.srcElement;

	if (/loaded|complete|undefined/.test(script.readyState)) {

		if (script.detachEvent && !isOpera) {

			script.detachEvent('onreadystatechange', onScriptLoad);

		} else {

			script.removeEventListener('load', onScriptLoad);

		}

		var head;

		if (head = script.parentNode) {

			try {

				if (script.clearAttribute) {

					script.clearAttribute();

				} else {

					for (var prop in script) {

						delete script[prop];

					}

				}

			} catch (e) { }

			head.removeChild(script);

		}

	}

}

もう一つの問題を見てください.今はスクリプトaがスクリプトbに依存しています.aは必ずbがロードされて実行されるまで待つべきです.どうすればいいですか?
1.シリアル読み込み、すなわち、次の読み込み(遅く)
2.並列ローディング
第一の方法は何も言うことはありません.ここで第二の方法を言います.
まず一つの属性を紹介します.async
scriptのasync属性がtrueである場合、スクリプトの実行順序は非同期であり、DOMに加入する順序では実行されません.falseであれば加入順に実行されます.
scriptタグが直接HTMLに符号化された場合、黙認されているasync属性はfalseであり、scriptがdocument.create Element('script')によって作成された場合、async属性はtrueである.
検出方法:var script=document.creat Element('script');script.async==true;
測定結果:IE 6-9,Opera 11,Safari 5はサポートされていません.
もう一つのプロパティを紹介します.
defer属性は、ページローディングまでにスクリプトの実行を遅延させるかどうかを規定しています.具体的には、最後に与えられたリンクを参照してください.
トリガー方式:script.defer='defer'
検出方式:var script=document.creat Element('script');script.defer==false;
検出結果:すべてのブラウザがサポートされています.
同じ点
違い点
asyncまたはdeferを持っているscriptはすぐにダウンロードされます.ページ解析をブロックしないで、オプションのonloadイベント処理を提供しています.scriptダウンロードが完了したら呼び出して、このscriptに関連する初期化作業をします.
scriptは実行するタイミングが違います.asyncのscriptを持っています.ダウンロードが完了したら実行します.もちろんwindowのonloadの前です.これは、これらのスクリプトがページに表示される順序では実行されないことを意味します.スクリプトが相互に依存し、実行順序に関連していれば、大きな問題が発生する可能性があります.deferを有するスクリプトは、ページに表示される順序で実行されることを確認します.ページ解析が完了した後、DOMConentLoadedで実行されるタイミングです.件前です
続いて先ほどの問題について話します.私達が関心を持っているのは誰が先にローディングするのかではなく、実行順の問題です.だからブラウザがasync属性をサポートするなら、falseに設定して、必要な順番でapendChildを実行すればいいです.しかし、この方式は明らかに互換性がないです.
まだdeferがあります.ブラウザは全部サポートしています.
最後にScript方式とXHR方式で比較します.
長所
欠点
1.ドメイン横断能力を持つ2.ActiveXがオフになってもIEで3.xhrをサポートしない古いブラウザで実行できます.
1.戻ってきたデータはjsコードとしてフォーマットしなければなりません.xhrが返したデータはどんなフォーマットでもいいです.XML、JSON、プレーンテキストなど2.GET要求だけをサポートしています.POST 3はサポートしていません.要求は非同期かはブラウザによって異なります.xhrはコントロールできます.信頼されていないソースからJSONデータを取得すると、コード実行前にこれらのデータを確認することができません.一方、xhrはいくつかのツールでデータを分析することができます.例えば、json.jsです.
もう一つの違いは、Scriptノードによってロードされたファイルを動的に作成し、現在のコンテキストでeval()を呼び出して処理すると、このファイルに定義されている変数と関数はすべてグローバルです.ロードしたいデータは部分的にのみ利用可能であれば、xhrを使いましょう.
この2つの方法はそれぞれ利点があります.全体として、コードをロードする必要があるなら、動的にscriptノードを作成する方式を使って、データを要求するなら、xhrを使用したほうがいいです.
いくつかの文章を紹介して拡大して読みます.
readyStateの5つの状態の詳細
また動的ローディングスクリプト.ieの下でscript ElementのreadyState状態を言います。
つのie 6の中でscriptノードのロードの問題を分かち合います。
jsの並列非同期とシリアル非同期
scriptのdefer&async