JavaScript でクロスブラウザ イベント処理メカニズムを作成 [Blue-Dream 制作]_javascript スキル

WBOY
リリース: 2016-05-16 18:23:21
オリジナル
1206 人が閲覧しました

互換性の問題はクラス ライブラリを使用すると簡単に解決できますが、そのメカニズムについて少しずつ説明していきます。
まず、DOM Level2 はイベント処理用の 2 つの関数

addEventListenerremoveEventListener を定義します。どちらも EventTarget インターフェースからのものです。 🎜>

コードをコピーします コードは次のとおりです。 element.addEventListener(eventName,listener,useCapture); >element .removeEventListener(eventName,listener,useCapture);

EventTarget インターフェイスは通常、Node または Window インターフェイスから実装されます。
たとえば、次のようになります。



コードをコピー
コードは次のとおりです: 関数loadHandler() { console.log ('ページが読み込まれました!')
}
window.addEventListener('load',loadHandler, false);


削除中リスナーは、removeEventListener を使用して簡単に実行できます。削除されたハンドルと追加されたハンドルが関数を参照していることに注意してください。

完璧な世界では、関数はここで終了します。
しかし、IE は独自の 2 つの関数attachEvent と detachEvent が定義されており、addEventListener とremoveEventListener を置き換えます。
そのため、実際に行う必要があるのは、IE ブラウザと w3c 標準間のイベント処理の違いに対処することです。

モニタリングを追加し、リスナーを削除するには、次のように記述します。




コードをコピー

コードは次のとおりです: functionloadHandler() { alert('ページが読み込まれました!'); } window.attachEvent('onload',loadHandler) // リスナーを追加します
window.detachEvent ('onload',loadHandler); // モニタリングを削除します


表面から、IE と w3c の間に 2 つの違いがあることがわかります。
1 の前に「on」プレフィックスがあります。
2. useCapture の 3 番目のパラメーターは削除されました。
実際には、これら 2 つの違いについてはさらに分析していきます。共通関数



コードをコピー

コードは次のとおりです。 function addListener(element,eventName 、ハンドラー) { if (element.addEventListener) { element.addEventListener(eventName, handler, false); }
else if (element.attachEvent) {
element.attachEvent( 'on' イベント名, ハンドラー);
}
else {
element['on' イベント名] = ハンドラー;
}
}
関数 RemoveListener(要素, イベント名, ハンドラー) {
if (element.addEventListener) {
element.removeEventListener(eventName, handler, false);
}
else if (element.detachEvent) {
element.detachEvent('on'
}
else {
element['on'eventName] = null;


注意すべき点が 2 つあります。上記の関数について:
1. まず、IE が徐々に標準に近づいているため、最初にこのブランチの w3c 標準を測定するのが最善です。
2.

パフォーマンスの最適化
上記の関数では、各バインディング イベントにはブランチが必要です。
このように、事前に検出するために「実行前」に変更する必要があります。 document.body を使用しない理由は、ドキュメントの準備ができていないときに document.body がすでに存在しているためです。
このように、関数は



コードをコピー


コードは次のとおりです:

var addListener, RemoveListener,
/* テスト要素 */
docEl = document.documentElement;
// addListener
if (docEl.addEventListener) {
/* `addEventListener` がテスト要素に存在する場合、`addEventListener` を使用する関数を定義 */
addListener = function (element,eventName, handler) {
element.addEventListener(eventName, handler, false);
};
}
else if (docEl.attachEvent) {
/* `attachEvent` がテスト要素に存在する場合、`attachEvent` を使用する関数を定義 */
addListener = function (要素, イベント名, ハンドラー) {
element.attachEvent('on' イベント名, ハンドラー);
};
}
else {
/* どちらのメソッドもテスト要素に存在しない場合は、フォールバック戦略に関数を定義します */
addListener = function (element,eventName,handler) {
element['on ' イベント名] = ハンドラー;
};
}
//removeListener
if (docEl.removeEventListener) {
removeListener = function (element,eventName, handler) {
element.removeEventListener(eventName, handler, false);
};
}
else if (docEl.detachEvent) {
removeListener = function (要素, イベント名, ハンドラー) {
要素.detachEvent('on' イベント名, ハンドラー);
};
}
else {
removeListener = function (要素, イベント名, ハンドラー) {
要素['on' イベント名] = null;
};
}

これは回避済每次绑定都判断が必要です。
上の利点は、これにも 2 つのハードコードがあります。 代コード量の増加を除いて、ある点はハードウェア推测を使用していることです。これは安全ではありません。
不安全な检测
下の二つの例文説明。ある状況下ではこれは十分安全ではありません。
复制代 代码如下:

// Internet Explorer の場合
var xhr = new ActiveXObject('Microsoft.XMLHTTP');
if (xhr.open) { } // エラー
var element = document.createElement('p');
if (element.offsetParent) { } // エラー

例: IE7 下の typeof xhr.open === 'unknown'。 详细参考feature-detection
所以我们提倡の检测方式は
复制代 代以下:

var isHostMethod = function (オブジェクト, メソッド名) {
var t = オブジェクトの種類[メソッド名];
return ((t === '関数' || t === 'オブジェクト') && !!オブジェクト[メソッド名]) || t === '不明';
};

この样我们上の优化関数。再次改进成この样
复制代代码如下:

var addListener, docEl = document.documentElement;
if (isHostMethod(docEl, 'addEventListener')) {
/* ... */
}
else if (isHostMethod(docEl, 'attachEvent')) {
/* ... */
}
else {
/* ... */
}

失われたこの指针
この指针の处理.IE w3c との違いは、w3c の関数の指示は、その句柄を決定する DOM 要素を指示することです。 而IE下破总はウィンドウを指します。
复制代代码如下:

// IE
document.body.attachEvent( 'onclick', function () {
alert(this === window) // true
alert(this === document.body) // false
});
// W3C
document.body.addEventListener('onclick', function () {
alert(this === window); // false
alert(this === document.body) ); // true
});

这个问题修正起来也不算麻烦
复制代代码如下:

if (isHostMethod(docEl, 'addEventListener')) {
/* ... */
}
else if (isHostMethod(docEl, 'attachEvent')) {
addListener = function (element, イベント名, handler) {
element.attachEvent('on' イベント名, function () {
handler.call(element, window.event);
});
};
}
else {
/* ... */
}

その後、呼び出しを使用してハンドラーのポインターを内部的に修正するだけです。実際、ここで密かに修正された問題があることに誰もが気づいているはずです。は最初の関数を通過せず、グローバルな世界に残されます。そのため、ここでも次のような大きな問題を修正しました。しばらく停止して簡単なテストを行うことができます。
1. ブラウザー間の互換性 2. このポインターが指す互換性
テストコードは次のとおりです:


ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
最新の問題
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート