jsにおけるロードイベントを深く理解する。


前の話
ロードイベントというと、Windows.onloadを思い出すかもしれませんが、実際にロードイベントは大きなイベントです。ここではロードイベントを詳しく紹介します。
ロード
ロードイベントは最も一般的なイベントで、ページが完全にロードされると(すべての画像、javascriptファイル、CSSファイルなどの外部リソースを含む)、Windows上のロードイベントがトリガされます。
[注意]IE 8-ブラウザはこのイベントのためにsrcellment属性を設定しません。他のブラウザのtarget属性はdocumentを指します。

window.onload = function(e){
 e = e || event;
 var target = e.target || e.srcElement;
 //IE8-     null,       document
 console.log(target);
}
ロードイベントは、documentオブジェクトだけでなく、様々な外部リソースの上で発生します。ウェブページをブラウズするということは、様々なリソースをロードする過程で、画像、スタイルシート、スクリプト、ビデオ、オーディオ(audio)、Ajax要求(XMLttpRequest)などがあります。これらのリソースとdocumentオブジェクト、windowオブジェクト、XMLHttp Request Uploadオブジェクトは、いずれもloadイベントをトリガします。
[注意]ページがブラウザキャッシュから読み込まれた場合、ロードイベントは発生しません。
画像とフレームワークのiframeは、ロードイベントをトリガすることもできます。
[注意]画像のsrc属性を指定する前にイベントを指定します。画像はsrc属性を設定してからダウンロードします。

var img = new Image();
img.onload = function(){
 document.body.appendChild(img);
}
img.src="http://sandbox.runjs.cn/uploads/rs/26/ddzmgynp/chunfen.jpg";

<iframe id="test" src="http://cnblogs.com" frameborder="0"></iframe>
<script>
test.onload = function(){
 console.log(666);
}
</script>
script要素は、動的にロードされたjavascriptファイルがロードされたかどうかを開発者が確認するために、ロードイベントをトリガすることもできる。画像と違って、script要素のsrc属性が設定されてドキュメントに追加された場合にのみ、javascriptファイルのダウンロードが開始されます。つまり、src属性の指定とイベントハンドラの優先順位は重要ではないです。
[注意]IE 8-ブラウザはこの用法をサポートしていません。

var script = document.createElement('script');
script.onload = function(){
 console.log(666);
}
document.body.appendChild(script);
script.src=http://files.cnblogs.com/files/xiaohuochai/excanvas.js;
同様に、link要素は、ロードイベントをトリガすることができ、互換性の問題がない。scriptと同様に、href属性が指定されておらず、文書にlink要素を追加する前にスタイルシートのダウンロードを開始しません。
同様に、link要素は、ロードイベントをトリガすることができ、互換性の問題がない。scriptと同様に、href属性が指定されておらず、文書にlink要素を追加する前にスタイルシートのダウンロードを開始しません。
error
ロードイベントはロード成功時にトリガされますが、errorイベントは正反対で、ロード失敗時にトリガされます。ロードイベントをトリガできる要素は、errorイベントをトリガすることができます。
try-catchで処理されていないエラーは、いずれもwindowオブジェクトのerrorイベントをトリガします。
errorイベントは、エラーメッセージ、エラーがあるURL、行番号の3つのパラメータを受信することができる。多くの場合、エラーメッセージだけが有用であり、URLはドキュメントの位置だけを提供しているため、行番号というコードラインは埋め込まれたjavascriptコードから出てもいいし、外部のファイルから出てもいいです。
Oneerrorイベントハンドラを指定するには、DOM 0レベルの技術を使ってもいいし、DOM 2レベルのイベントの標準フォーマットを使ってもいいです。

//DOM0 
window.onerror = function(message,url,line){
 alert(message);
}
//DOM2 
window.addEventListener("error",function(message,url,line){
 alert(message);
});
ブラウザが標準のエラーメッセージを表示するかどうかは、Oneerrorの戻り値に依存します。戻り値がfalseであれば、コンソールにエラーメッセージを表示する。戻り値がtrueであれば、表示されません。

//         
window.onerror = function(message,url,line){
 alert(message);
 return false;
}
a;
//          
window.onerror = function(message,url,line){
 alert(message);
 return true;
}
a;
このイベントハンドラは、ブラウザがバグを報告するのを避ける最後の防御線です。理想的には、可能であればそれを使うべきではない。try-catch文を適切に使うことができれば、ブラウザにエラーがなく、errorイベントをトリガしません。
画像もerrorイベントに対応しています。画像のsrc特性の中のURLが識別可能な画像フォーマットに戻らない限り、errorイベントがトリガされる。この時のerrorイベントはDOM形式に従い、画像を対象としたイベントオブジェクトを返します。
errorイベントが発生した時、画像のダウンロードはもう終わりました。つまり再ダウンロードはできません。ただし、errorイベントでは、画像のsrc属性を再設定し、予備画像のアドレスを指すことができる。

var image = new Image();
document.body.appendChild(image);
image.onerror = function(e){
 image.src = 'smileBackup.gif';
}
image.src = 'smilex.gif';
abort
要素のロードが中止された場合、(ロード中にESCキーを押すと、ロードが停止されます)、イベントをトリガします。
[注意]IEブラウザのみのサポート

var image = new Image();
image.onabort = function(){
 console.log(111);
}
document.body.appendChild(image);
image.src = 'http://sandbox.runjs.cn/uploads/rs/26/ddzmgynp/chunfen.jpg';
unload
ロードイベントに対応するunloadイベントは、ドキュメントが完全にアンインストールされた後にトリガされます。一般に、ページを更新するとイベントが発生します。
chrome/firefox/safariブラウザはalertなどのダイアログボックスを阻止します。IEブラウザはconsone.log()などのコンソールの表示を阻止します。

window.onunload = function(e){
 //chrome  ,firefox    ,IE  666
 alert(666);
}

window.onunload = function(e){
 //chrome firefox     666,IE    
 console.log(666);
}
beforeunload
beforeunloadイベントは、ウェブページを閉じたり、ウェブページを更新したりする際にトリガされます。これは一般的にユーザーがうっかりページを閉じないようにするために使われます。
beforeunloadイベントを有効にするには、次の二つの条件の一つを満たす必要があります。1、イベントハンドラは真の値を返します。2、イベントオブジェクトevent.return Valueは真の値を返します。二つの条件が同時に満足すれば、最初の条件に準じる。
chrome/safari/firefoxはダイアログで指定されたテキストを表示せず、標準のテキストのみを表示します。IEブラウザは、ダイアログに戻り値またはreturn Value値を表示します。

window.onbeforeunload = function(e){
 e = e || event;
 //IE         ,           
 e.returnValue = '    ?'; 
}
DOMContentLoaded
windowのonloadイベントはページの中のすべてのロードが終わった時に触発されますが、この過程はロードする外部の資源が多すぎて大変な費用がかかります。DOMContentLoadedイベントは、完全なDOMツリーを形成するとトリガされ、画像、javascriptファイル、CSSファイル、または他のリソースがダウンロードされたかどうかを無視する。ロードイベントと違って、DOMContentLoadedはページでダウンロードしたイベントハンドラの早期追加をサポートしています。これはユーザーができるだけ早くページと対話できることを意味します。
[注意]ウェブページのjavascriptスクリプトは同期して実行されるので、DOMContentLoadedイベントの傍受関数を定義して、すべてのシナリオの先頭に置くべきです。シナリオが詰まると、DOMContentLoadedイベントのトリガが遅くなります。
DOMContentLoaded事件を処理するには、documentまたはwindowのために対応するイベントハンドラを追加することができますが、このイベントはwindowに泡を噴きますが、その目標は実際にdocumentです。
[注意]IE 8-ブラウザはイベントをサポートしていません。

window.addEventListener('DOMContentLoaded',function(e){
 console.log(1);
})
このイベントをサポートしていないブラウザについては、ページローディング中に1時間0ミリ秒のタイムアウトコールを設定し、ページの最初のタイムアウト呼び出しとして必要です。

setTimeout(function(){
 console.log(1); 
},0) 
readystatechange
readystatechangeイベントは、DockmentオブジェクトとXMLtHttpRequestオブジェクトで発生し、それらのreadyState属性が変化したときにトリガされます。
このイベントの目的は、ドキュメントまたは要素の読み込み状態に関する情報を提供することです。readystatechangeイベントをサポートする各オブジェクトにreadyState属性があります。下記の5つの値のうちの一つが含まれているかもしれません。

uninitialized(    ):           
loading(    ):        
loaded(    ):        
interactive(  ):       ,        
complete(  ):        
これらの状態は直観的に見えるが、すべての対象がreadyStateという段階を経験するわけではない。言い換えれば、ある段階がオブジェクトに適用されない場合、オブジェクトはこの段階をスキップする可能性があります。どの段階がどの対象に適用されるかは決まっていません。明らかに、これはreadystatechangeイベントが常に4回より少ないことを意味し、readyState属性の値も常に連続しているわけではない。
documentにとって、「interactive」という値のreadyStateは、DOMContentLoadedとほぼ同じタイミングでreadystatechangeイベントをトリガします。この時、DOMツリーはすでにロード済みで、安全に操作できますので、インタラクティブな段階に入ります。しかし同時に、画像や他の外部ファイルは必ずしも利用可能ではない。

//'interactive' 'complete'
document.onreadystatechange = function(e){
 if(document.readyState == 'uninitialized'){
  console.log('uninitialized');
 }
 if(document.readyState == 'loading'){
  console.log('loading');
 }
 if(document.readyState == 'loaded'){
  console.log('loaded');
 }
 if(document.readyState == 'interactive'){
  console.log('interactive');
 }
 if(document.readyState == 'complete'){
  console.log('complete');
 } 
}
ロードイベントと一緒に使用する場合、二つのイベントのトリガの順序は予測できません。多くの外部リソースが含まれているページでは、ロードイベントがトリガされる前に相互作用の段階に入る。少ないまたは小さい外部リソースを含むページでは、readystatechangeイベントがロードイベントの前に発生するとは言い難いです。
問題をより複雑にするのは、対話段階が早くなり、完成段階より遅くなるかもしれません。順序を確保できません。より多くの外部リソースが含まれているページでは、相互作用の段階がより早く完成段階に出現する可能性がある。ページに外部リソースが少ない場合は、相互作用段階よりも完成段階が先になる可能性が高い。そのためには、できるだけ先行機をつかむために、相互作用と完成段階を同時に測定する必要がある。

document.onreadystatechange = function(){
 if(document.readyState == 'interactive' || document.readyState == 'complete'){
  console.log('loaded');
  document.onreadystatechange = null;
 }
}
上記のコードに対しては、readystatechangeイベントがトリガされると、document.readyStateの値が検出され、現在はインタラクティブな段階に入っているかどうか、または完了段階に入っているかどうかを確認する。もしそうなら、他の段階で実行しないように、対応するイベントハンドラを削除します。
また、IE 10-ブラウザは、script要素とlink要素にreadystatechangeイベントをトリガすることをサポートし、外部のjavascriptまたはcssファイルが既にロードされているかどうかを判定するために使用される。

var script = document.createElement('script');
script.onreadystatechange = function(){
 if( script.readyState == 'loaded' || script.readyState == 'complete'){
  console.log('loaded');
  script.onreadystatechange = null;
 }
}
script.src="js/digit.js";
document.body.appendChild(script);

var link = document.createElement('link');
link.rel="stylesheet";
link.onreadystatechange = function(){
 if( link.readyState == 'loaded' || link.readyState == 'complete'){
  console.log('loaded');
  link.onreadystatechange = null;
 }
}
link.href="test.css" rel="external nofollow" ;
document.getElementsByTagName('body')[0].appendChild(link);
以上が本文の全部です。本文の内容は皆さんの学習や仕事に一定の助けをもたらしてくれると同時に、私達を応援してください。