JS事件モデル


JS事件モデル
観察者モード
観察者モードは、複数の観察者にあるテーマオブジェクトを同時に傍受することができます.このテーマのオブジェクトの状態が変化したら、すべての購読者に通知して、反応ができるようにします.JSのイベントモデルは、対応するイベントがトリガされると、そのイベントを傍受するすべての傍受関数が呼び出される観察者モードの具現である.
以下はJSで実現される観察者モードのコードです.
var events = (function() {
  var topics = {};

  return {
    publish: function(topic, info) {
      console.log('publish a topic:' + topic);
      if (topics.hasOwnProperty(topic)) {
        topics[topic].forEach(function(handler) {
          handler(info ? info : {});
        })
      }
    },
    subscribe: function(topic, handler) {
      console.log('subscribe an topic:' + topic);
      if (!topics.hasOwnProperty(topic)) {
        topics[topic] = [];
      }

      topics[topic].push(handler);
    },
    remove: function(topic, handler) {
      if (!topics.hasOwnProperty(topic)) {
        return;
      }

      var handlerIndex = -1;
      topics[topic].forEach(function(element, index) {
        if (element === handler) {
          handlerIndex = index;
        }
      });

      if (handlerIndex >= 0) {
        topics[topic].splice(handlerIndex, 1);
      }
    },
    removeAll: function(topic) {
      console.log('remove all the handler on the topic:' + topic);
      if (topics.hasOwnProperty(topic)) {
        topics[topic].length = 0;
      }
    }
  }
})();
使用事例:
//      
var handler = function(info) {
    console.log(info);
}
//  hello  
events.subscribe('hello', handler);

//  hello  
events.publish('hello', 'hello world');
事件と事件の流れ
イベントはブラウザやドキュメントと対話する瞬間で、ボタンをクリックしたり、フォームを記入したりするなど、JSとHTMLの間の橋渡しです.DOMはツリー構造であり、同時に親子ノードにイベントを結びつける場合、この2つのイベントの発生順序はどのように決定されますか?これは、イベントフローの概念に関連しており、ページでイベントを受け入れる順序を説明している.
イベントフローは2つあります
  • 事件発泡(Event Capturing):下から上への伝播方式である.イベントの最初は、最も具体的な要素(ドキュメント内のネストレベルが最も深いノードによって承認され、すなわちDOM最低層のサブノード)によって徐々に上に向かって、最も具体的でないノード、すなわちDOMの中のトップの親ノードに伝播される.
  • イベントキャプチャ(Event Bbbbling):イベントの発泡とは逆である.イベントの最初は、あまり具体的ではないノードによって最初にイベントを受け入れられ、最も具体的なノードによって最後にイベントを受け入れる.
  • イベントモデル
    DOM 0級モデル
    元のイベントモデルとしても知られており、このモデルではイベントは伝播しない、すなわちイベントフローの概念がない.イベントバインディング監聴関数は比較的簡単で、2つの方法があります.
  • HTMLコードに直接紐付けされています.
  • JSコードで属性値を指定します.
    var btn = document.getElementById('.btn');
    btn.onclick = fun;
    でリスニング機能を削除します.
      btn.onclick = null;
  • この方式はすべてのブラウザが対応していますが、論理と表示は分離されていません.
    IEイベントモデル
    IEイベントモデルには2つのプロセスがあります.
  • 事件処理フェーズ.イベントがターゲット要素に到達し、ターゲット要素の待ち受け関数をトリガします.
  • 事件の発泡段階.イベントはターゲット要素からdocumentに泡を噴き出し、経過したノードがイベント傍受関数と結びつけられているかどうかを順次チェックし、もしあれば実行する.
  • イベントバインディングの待ち受け関数の方法は以下の通りです.
    attachEvent(eventType, handler)
    イベントの待ち受け関数を削除する方法は以下の通りです.
    detachEvent(eventType, handler)
    パラメータの説明:
  • eventType指定イベントタイプ(アドオン)
  • handlerはイベント処理関数
  • である.
    Example:
    var btn = document.getElementById('.btn');
    btn.attachEvent(‘onclick’, showMessage);
    btn.detachEvent(‘onclick’, showMessage);
    DOM 2級モデル
    W 3 C標準モデルに属し、現代ブラウザ(IE 6-8以外のブラウザ)はこのモデルをサポートしています.このイベントモデルでは、一つのイベントには三つのプロセスがある.
  • イベントキャプチャフェーズ(capturing phase).イベントは、documentからターゲット要素に下方に伝播し、経過したノードがイベント傍受関数と結びつけられているかどうかを順次チェックし、もしあれば実行する.
  • 事件処理フェーズ.イベントがターゲット要素に到達し、ターゲット要素の待ち受け関数をトリガします.
  • 事件の発泡段階.イベントはターゲット要素からdocumentに泡を噴き出し、経過したノードがイベント傍受関数と結びつけられているかどうかを順次チェックし、もしあれば実行する.
  • イベントバインディングの待ち受け関数の方法は以下の通りです.
    addEventListener(eventType, handler, useCapture)
    イベントの待ち受け関数を削除する方法は以下の通りです.
    removeEventListener(eventType, handler, useCapture)
    Example:
    var btn = document.getElementById('.btn');
    btn.addEventListener(‘click’, showMessage, false);
    btn.removeEventListener(‘click’, showMessage, false);
    パラメータの説明:
  • eventType指定イベントタイプ
  • handlerはイベント処理関数
  • である.
  • useCaptureは、Trapフェーズで処理するかどうかを指定するためのbootleanであり、一般的にfalseに設定されており、IEブラウザと一致している.
  • イベントオブジェクト
    イベントがトリガされると、イベントに関する属性や方法が含まれているイベントオブジェクトが作成されます.オブジェクトは、最初のパラメータとして傍受関数に渡されます.
  • DOMイベントモデルにおけるイベントオブジェクトの一般的な属性:
  • typeイベントタイプ
  • を取得するために使用されます.
  • target取得イベントターゲット
  • stopPropagation()イベントの発泡を防止する
  • preventDefault()イベントのデフォルト挙動を阻止する
  • IEイベントモデルにおけるイベントオブジェクトの一般的な属性:
  • typeイベントタイプ
  • を取得するために使用されます.
  • srcerement取得イベント目標
  • cancel Bubble阻止イベントブリスター
  • return Valueイベントのデフォルト動作を阻止する
  • Event Wrapper
    イベントモデルの違いとEventオブジェクトの違いにより、各ブラウザに対応する目的を達成するために、Event Wrapperを追加することができます.各ブラウザに一致するイベント操作インターフェースを提供しなければなりません.
    var eventUtils={
         //     
         addHandler:function(element,type,handler){
           if(element.addEventListener){
             element.addEventListener(type,handler,false);
           }else if(element.attachEvent){
             element.attachEvent('on'+type,handler);
           }else{
             element['on'+type]=handler;
           }
         },
         //     
         removeHandler:function(element,type,handler){
           if(element.removeEventListener){
             element.removeEventListener(type,handler,false);
           }else if(element.detachEvent){
             element.detachEvent('on'+type,handler);
           }else{
             element['on'+type]=null;
           }
         },
        //      
        //IE   event             window   
        getEvent:function(event){
           return event?event:window.event;
        },
        //    
        getType:function(event){
         return event.type;
        },
        getElement:function(event){
         return event.target || event.srcElement;
        },
        //      
        preventDefault:function(event){
         if(event.preventDefault){
          event.preventDefault();
         }else{
          event.returnValue=false;
         }
        },
        //    
       stopPropagation:function(event){
       if(event.stopPropagation){
         event.stopPropagation();
       }else{
         event.cancelBubble=true;
        }
       }
      }
    参考:
  • DOM事件の謎解き
  • イベントエージェント
    イベントは発泡中に親ノードにアップロードされるので、サブノードの傍受関数を親ノードに定義し、親ノードの傍受関数によって複数のサブ要素のイベントを一括して処理する方法をイベントエージェントと呼ぶことができる.
    私たちはdiv要素を持っています.ボタンは3つあります.
    私たちは親ノードにおいて、一時的にすべてのサブノードに傍受関数を登録することができます.
    var box = document.getElementById('box');
    
    box.addEventListener('click', function(event) {
      if (event.target.tagName.toLowerCase() === 'input') {
        // some code
      }
    });
    イベントをカスタマイズ
    JSには、click、mouseoverなど多くのイベントが内蔵されていますが、内蔵イベントはやはり限られています.時には、自分で三つの連打、threeclickなどのイベントを定義したいです.どのようにカスタムイベントを実現しますか?
  • まずイベントを作成します.以下の方法が使えます.
  • var event = new Event('threeclick', {"bubbles":true, "cancelable":false});
  • その後、イベントのための傍受関数の登録が必要です.
  • target.addEventListener('threeclick', hello, false);
  • 最後に、私たちは適切なタイミングでイベントをトリガします.私たちはdispatch Event関数を使用することができます.この方法は、現在のノードで指定されたイベントをトリガし、それにより、傍受関数の実行をトリガする.この方法はブール値を返します.一つの傍受関数がEvent.prevent Defaultを呼び出したらfalseを返します.そうでなければtrueを返します.
  • target.dispatchEvent(event);
    JQuery Eventモデル
    JQueryが解決した主な問題はブラウザの互換性の問題です.自分のイベントモデルの実現方法があります.主に以下の特性があります.
  • は、JQuery.Eventオブジェクトを再定義し、イベント属性と方法を統一し、イベントモデル
  • を統一しました.
  • は、一つのイベントタイプに複数のイベントハンドラ関数を追加してもよく、複数のイベントタイプのイベントハンドラ関数
  • を一度に追加しても良い.
  • は、カスタムイベント(イベント名空間)
  • をサポートしています.
  • は、toggaleを提供しています.
  • は、one、live-die、delegate-undelegate
  • を提供しています.
  • は、統一イベントパッケージ、バインディング、実行、廃棄メカニズムを提供しています.
  • $(document).ready()
  • JQueryイベントの具体的なコードは以下の通りです.https://github.com/jquery/jqu...JQueryイベントの具体的な使い方は自分で調べてください.