メインコンテンツへ移動

JS 学習ノート 6_イベント

無料2015-04-11#JS#js事件

本稿ではイベントフロー、イベントデリゲーション、いくつかの常識及びパフォーマンス最適化戦略を紹介します

##1.イベントバブリング##

内から外へのイベント伝播(画面から矢が飛び出してくる感じ)

##2.イベントキャプチャ##

表から里へのイベント伝播(紙背に力を通す感じ)

##3.DOM イベントフロー(DOM2 レベル)##

イベントキャプチャ段階 -> 目標段階 -> イベントバブリング段階(針を画面に刺し込んで、縫い物をする感じ)

イベントキャプチャは DOM ツリーの根から葉へのイベント伝播なので、根に近い位置でイベントをキャプチャ(event.stopPropagation)でき、葉がイベント信号を受け取らないようにできます

イベントバブリングは葉から根への原路復帰プロセスなので、根に近い位置で葉のイベントを集中処理(event.target)できます。これがいわゆるイベントデリゲーションで、集中処理により複数の葉にイベントハンドラをバインドすることを避け、応答速度を低下させるのを防げます

目標段階は仕様规范要求ですが、ブラウザはあまりサポートしていません

注意:[IE9+] はイベントキャプチャをサポートし、イベントバブリングは全ブラウザサポートです

##4.イベントハンドラを追加するいくつかの方法##

  1. HTML:on イベント名 = strCode イベント処理関数が直接アクセスできる属性 = グローバル属性 + 要素が所在する form 中の属性 + 要素自身の属性

自動のスコープ拡張方式は以下に相当:

    function(){
      with(document){//グローバル属性
        with(this.form){//フォーム属性
          with(this){
            //自身属性
          }
        }
      }
    }
    

イベント処理関数はこれら多くの属性に直接アクセスできるので、このようにできます:

    <form method="post">
      <input type="text" name="user_name" value="">
      <input type="button" value="ユーザー名取得" onclick="alert(user_name.value)">
    </form>
    

2. DOM0 レベル:elem.on イベント名 = functionName/null;

この方式で追加されたイベントハンドラはバブリング段階で実行され、直接アクセスできる属性 = グローバル属性 + 要素自身の属性

  1. DOM2 レベル:(現代ブラウザがサポートする)elem.add/removeEventListener(イベント名,functionName, false/true);

false はイベントバブリング段階で追加することを示し、true はイベントキャプチャ段階で追加することを示します。直接アクセスできる属性は上記と同じ

  1. [IE8-]:elem.attach/detachEvent(on イベント名(on を捨てて���いけません), functionName);

直接アクセスできる属性はグローバル属性のみで、しかも同一イベントに追加された複数のハンドラの中で、最後に追加されたものが最初に実行され、DOM2 レベル標準と逆です

P.S.[IE8-] はイベントバブリングのみサポートするので、第 3 パラメータはなく、デフォルト(也只能是)イベントバブリング段階で追加

##5.イベントオブジェクトの用途は?##

btn.onclick = function(event){
  //event.target;イベントソース取得
  //event.preventDefault();デフォルト動作キャンセル、例えばリンクのジャンプ動作
  //event.stopPropagation();イベント伝播阻断
  //还有一些不常用的
}

注意:上記コードは全ブラウザ互換ではありません。イベントオブジェクトの属性も完全ではありません。詳細情報は [JS 原生イベント処理(クロスブラウザ)](/articles/js 原生事件処理(跨浏览器)/) を参照

##6.イベント分類##

  1. UI イベント

  2. フォーカスイベント

  3. マウスイベント

  4. ホイールイベント

  5. テキストイベント

  6. キーボードイベント

  7. 合成イベント(IME で入力)

  8. 変動イベント(DOM 構造更新)

  9. HTML5 イベント

  10. デバイスイベント(特定デバイス、例えばゲーム機)

  11. タッチとジェスチャーイベント

##7.イベントデリゲーション##

イベントバブリングを利用してイベントハンドラを削減し、パフォーマンスを向上。document オブジェクトにイベントハンドラを追加して、より短いインタラクション準備時間を求めることさえできます(ページ要素とイベントハンドラの接続確立に時間が必要)

イベントデリゲーションの利点

  1. イベントハンドラ設定に必要な時間がより少ない。DOM アクセス回数が減るため

  2. 占有メモリ空間がより少ない。イベントハンドラが減るため

  3. インタラクション準備時間が短くなる。ページ要素とイベントハンドラの間で確立が必要な接続が減るため

  4. ページ応答速度が速くなる。ページ要素とイベントハンドラの間で確立する接続が減るため

##8.イベントハンドラを削除する際の注意事項##

対象要素が DOM ツリーから削除される前に、手動でバインドされたイベントハンドラを削除し、無効なイベントハンドラがメモリを占有するのを避けるべき

ページ unload 前に、ページ中のすべてのイベントハンドラを手動で削除するのが最善。[IE8-] はページ unload 時、イベントハンドラがメモリ中に滞留するため。unload イベントハンドラ中で削除可能

イベントハンドラを削除する実質は、ページ要素とイベントハンドラの間の接続を切断すること

##9.イベントをシミュレートする方法(つまりコードで指定イベントをトリガー)##

  1. event オブジェクトを作成

  2. event オブジェクトの各属性を初期化

  3. イベントをトリガー

注意:[IE8-] の実装は DOM 規範と異なります。DOM3 レベルのみがキーボードイベントを完璧にシミュレートできます

##10.常識及びパフォーマンス最適化戦略##

  1. 他のイベントをインターセプトする必要がある場合のみ、イベントハンドラをキャプチャ段階に追加。[IE8-] はイベントキャプチャをサポートしないため

  2. 動的に作成された img 要素に対して、src 属性を設定した時点で関連内容のダウンロードが開始。新しい要素が DOM ツリーに挿入されてから開始されるわけではない

  3. 動的に作成された script 要素に対して、DOM ツリーに挿入されてからダウンロードが開始

  4. 動的に作成された link 要素(外部スタイル読み込み用)に対して、head 部分に挿入して初めてブラウザ表現が一致することを保証。しかも外部スタイルはデフォルトで非同期ロード

  5. in 演算子でイベントサポートを検出。例えば:

    if('onload' in elem){
      //do sth
    }
    
  6. hover, mouseover, mouseout, mouseenter, mouseleave の違いは?

    • hover は CSS 疑似クラス。マウスが目標要素に入り、その中にいる時にトリガー。
    • mouseover はマウスイベント。マウスが目標要素に入った時にトリガー。ブラウザの広範なサポートを得ている。mouseenter に相当するが、nouseenter は完全サポートを得ていない。
    • mouseout は mouseover と逆。mouseleave は mouseenter と逆。後者は完全サポートを得ていない。
    • 本机テスト:FF と IE は全サポート。Chrome は enter/leave をサポートしない。
  7. イベントデリゲーションは最も重要な最適化戦略。もちろん、デリゲーションも完璧ではなく、デリゲーションはロジックの粘连を招く。例えば極端な場合、document オブジェクトに 1 つのイベントハンドラを追加するだけで済むが、それは非常に大きな関数になる。。。したがって、適切な場所でできるだけデリゲーションを使用すべき

  8. 適時に期限切れの時間ハンドラを削除するとメモリ占有を削減。これは空間面の最適化戦略

コメント

コメントはまだありません

コメントを書く