2011-07-09 6 views

答えて

12

FileReaderaddEventHandlerのようなメソッドを持っています。 EventTargetDOM Events仕様で定義されていますが、実装するにはDOMオブジェクトである必要はありません。 window,XMLHttpRequestおよびFileReaderは、EventTargetを実装する他のブラウザオブジェクトモデルオブジェクトです。

残念ながら、ブラウザのイベントターゲットのネイティブ実装にピギーバックする簡単な方法はありません...ブラウザオブジェクトからprototypeプロパティを使用して継承することができますが、一般的には非常に信頼性がありません。しかしプレーンJavaScriptですべてのメソッドを自分で実装するコードを書くには余りにも難しいことではありません。

function CustomEventTarget() { this._init(); } 

CustomEventTarget.prototype._init= function() { 
    this._registrations= {}; 
}; 
CustomEventTarget.prototype._getListeners= function(type, useCapture) { 
    var captype= (useCapture? '1' : '0')+type; 
    if (!(captype in this._registrations)) 
     this._registrations[captype]= []; 
    return this._registrations[captype]; 
}; 

CustomEventTarget.prototype.addEventListener= function(type, listener, useCapture) { 
    var listeners= this._getListeners(type, useCapture); 
    var ix= listeners.indexOf(listener); 
    if (ix===-1) 
     listeners.push(listener); 
}; 

CustomEventTarget.prototype.removeEventListener= function(type, listener, useCapture) { 
    var listeners= this._getListeners(type, useCapture); 
    var ix= listeners.indexOf(listener); 
    if (ix!==-1) 
     listeners.splice(ix, 1); 
}; 

CustomEventTarget.prototype.dispatchEvent= function(evt) { 
    var listeners= this._getListeners(evt.type, false).slice(); 
    for (var i= 0; i<listeners.length; i++) 
     listeners[i].call(this, evt); 
    return !evt.defaultPrevented; 
}; 

注意:上記のコードの私の頭の上から未検証ですが、動作する可能性があります。しかし、EventオブジェクトがDOMレベル3 defaultPreventedプロパティをサポートし、DOMレベル3のサポートがない場合はdispatchEvent戻り値をサポートするような制限があります。stopImmediatePropagation()(実装不可能な独自のEventオブジェクトに依存しない限りそれ)。また、階層やキャプチャ/バブリングの実装もありません。

だからIMO:あなたはDOMイベントモデルに参加するコードを書いてみることはあまりありません。プレーンJSコールバックの仕事のために、リスナーリストの独自の特別な実装を行っています。

+0

私は自分自身のイベントモデルを持っています。ハンドラを「イベントタイプ」にバインドし、ハッシュに格納し、このモデルを継承するオブジェクト(および他のユーティリティメソッド)を「トリガする」関数を呼び出します。デフォルトのイベントモデルは私のものよりも貴重な利点はないとお考えですか? – jayarjo

+1

ええ、利点は非常に小さいと思いますが、 'preventDefault' /' stopPropagation'/'stopImmediatePropagation'が確実に読み取れないため、' Event'の他の実装と実際に100%相互運用することはできません呼び出されました。だから、唯一の利点は、DOMイベントインターフェイスの親しみです...しかし、それは間違いなくかなりclunkyインターフェイスです。 – bobince

+1

私はこれを見つけました:http://www.w3.org/TR/DOM-Level-3-Events/#interface-CustomEvent、ここでW3Cはアプリケーション固有のイベントタイプを作成することを推奨しています。限り、私はまだ広くはサポートされていない参照してください、しかし、それはすべてのものが向いているようです。 – jayarjo

0

私はそれがjavascriptだと仮定します。通常、DOM要素への参照を取得できるオブジェクトはすべて、element.dispatchEvent関数を使用してイベントを送出できます。参照:それはEventTargetインタフェースを実装するdefinedあるので

https://developer.mozilla.org/en/DOM/document.createEvent

https://developer.mozilla.org/en/DOM/element.dispatchEvent

+0

はい、これらのページから来ました。つまり、FileReaderはDOM要素に関連していないか、または参照があるようです。しかしそれと同時に、dispatchEventメソッド自体があり、イベント(私が推測するDOMイベント)をディスパッチできます。混乱は少しありますか?私は、同様のプロパティを持つオブジェクトを作成する方法があるのだろうかと思った。 – jayarjo

+0

私はFileReaderを実装していませんので、推測だけですが、DOM要素が内部的にプライベートメソッドとして保持されていて、FileReaderのdispatchEventが内部のdispatchEventへの呼び出しを転送していたDOM要素、どうやって知っていますか? – phtrivier

+0

内部DOM要素はどういう意味ですか?このような現実世界の言葉はありますか、それともあなたは再び推測していますか? :)内部DOM要素があれば、FileReaderは何も転送する必要がないと思います。それ自体が一つかもしれない。 – jayarjo

3

bobince has the right ideaですが、彼のコードは単なる例です。実際のバトルテスト実装の場合は、Mr. Doob has one that he uses in three.jsです。

+2

ECMAScript APIのエミュレーションに関心がない場合は、[signals](http://millermedeiros.github.com/js-signals/)と[bacon](https://github.com/raimohanska/)も検討してください。 bacon.js)。 – bsimpson

1

jQueryは、通常のオブジェクトからイベントをディスパッチできます。 Here's a fiddle

function MyClass() { 
    $(this).on("MyEvent", function(event) { 
     console.log(event); 
    }); 

    $(this).trigger("MyEvent"); 
} 

var instance = new MyClass();