1. ホーム
  2. javascript

[解決済み] addEventListenerとonclickの比較

2022-03-22 21:07:31

質問

とはどう違うのですか? addEventListeneronclick ?

var h = document.getElementById("a");
h.onclick = dothing1;
h.addEventListener("click", dothing2);

上記のコードは別の.jsファイルに一緒に存在し、どちらも完全に動作します。

解決するには?

どちらも正しいのですが、それ自体がベストというわけではありませんし、開発者が両方のアプローチを選択した理由もあるでしょう。

イベントリスナー(addEventListenerとIEのattachEvent)

Internet Explorer の初期バージョンは、他の多くのブラウザとは異なる方法で javascript を実装しています。 9より前のバージョンでは attachEvent [ ドク ] メソッドのようになります。

element.attachEvent('onclick', function() { /* do stuff here*/ });

他のほとんどのブラウザ(IE 9以降を含む)では、以下のようになります。 addEventListener [ ドク ] のようになります。

element.addEventListener('click', function() { /* do stuff here*/ }, false);

この方法( DOMレベル2イベント ) を使用すると、理論的には1つの要素に無制限の数のイベントを付けることができます。唯一の現実的な制限は、クライアントサイドのメモリとその他のパフォーマンスに関するもので、これはブラウザごとに異なります。

上記の例では、無名関数[ ドクター ]. また、関数リファレンスを使用してイベントリスナーを追加することもできます[ 。 doc またはクロージャ[ doc ]:

var myFunctionReference = function() { /* do stuff here*/ }

element.attachEvent('onclick', myFunctionReference);
element.addEventListener('click', myFunctionReference , false);

のもう一つの重要な特徴は addEventListener は最後のパラメータで、リスナーがバブリングイベントにどのように反応するかを制御します[ ]。 ドクター ]. この例では false を渡していますが、これはおそらく95%のユースケースで標準的なものです。に相当する引数はありません。 attachEvent またはインライン・イベントを使用する場合。

インラインイベント(HTML onclick=""プロパティとelement.onclick)

javascriptをサポートしているすべてのブラウザでは、イベントリスナーをインラインで、つまりHTMLコードの中に置くことができます。 おそらくこれを見たことがあるはずです。

<a id="testing" href="#" onclick="alert('did stuff inline');">Click me</a>

経験豊富な開発者の多くはこの方法を敬遠しますが、シンプルで直接的な方法で仕事はできます。クロージャや無名関数は使えないし(ハンドラ自体は無名関数の一種ですが)、スコープの制御も制限されます。

もう1つの方法ですが

element.onclick = function () { /*do stuff here */ };

...は、インラインJavaScriptと同等ですが、(HTMLではなくスクリプトを書いているので)スコープをより制御でき、匿名関数、関数参照、クロージャを使用できる点が異なります。

インラインイベントの大きな欠点は、前述のイベントリスナーとは異なり、割り当てられるインラインイベントは1つだけであることです。インラインイベントは要素の属性/プロパティとして保存されます[ ]。 doc つまり、上書きすることができるのです。

例として <a> を上記のHTMLから削除します。

var element = document.getElementById('testing');
element.onclick = function () { alert('did stuff #1'); };
element.onclick = function () { alert('did stuff #2'); };

... 要素をクリックすると だけ の最初の割り当てを上書きしています。 onclick プロパティを2番目の値で上書きし、元のインラインHTMLの onclick プロパティもあります。ここで確認してみてください。 http://jsfiddle.net/jpgah/ .

大まかに言うと インラインイベントを使用しない . 特定のユースケースがあるかもしれませんが、そのユースケースが100%ないと確信できるのであれば、インラインイベントは使用しませんし、使用すべきではありません。

モダンJavascript(Angularなど)

この回答が最初に投稿されて以来、Angularのようなjavascriptフレームワークがはるかに普及してきました。Angularのテンプレートでは、このようなコードを目にすることができます。

<button (click)="doSomething()">Do Something</button>

これはインラインイベントのように見えますが、そうではありません。このタイプのテンプレートは、裏側でイベントリスナーを使用する、より複雑なコードに変換されます。私がイベントに関してここで書いたことはすべてそのまま適用されますが、少なくとも1つの層によって細かい部分から切り離されます。しかし、最新のJSフレームワークのベストプラクティスでは、このようなコードをテンプレートに記述することになっている場合、インラインイベントを使用しているように感じないでください -- そうではありません。

どれが一番いいの?

この問題は、ブラウザの互換性と必要性の問題です。1つの要素に複数のイベントをアタッチする必要があるのでしょうか?将来的にはそうなるのでしょうか?attachEventとaddEventListenerは必要です。そうでない場合は、インライン・イベントで事足りるように思えるかもしれませんが、可能性は低いかもしれませんが、少なくとも予測可能な未来に備える方がずっとよいでしょう。JSベースのイベントリスナーに移行しなければならない可能性があるのだから、そこから始めたほうがいい。インライン・イベントは使わないでください。

jQuery や他の javascript フレームワークは、DOM レベル 2 イベントの異なるブラウザの実装を汎用モデルにカプセル化するので、IEの履歴を反面教師として気にすることなく、クロスブラウザに準拠したコードを書くことができます。 jQuery を使用した同じコードで、すべてクロスブラウザに対応し、ロックする準備ができています。

$(element).on('click', function () { /* do stuff */ });

しかし、このためだけにフレームワークを購入する必要はありません。古いブラウザに対応するための小さなユーティリティを自作するのは簡単です。

function addEvent(element, evnt, funct){
  if (element.attachEvent)
   return element.attachEvent('on'+evnt, funct);
  else
   return element.addEventListener(evnt, funct, false);
}

// example
addEvent(
    document.getElementById('myElement'),
    'click',
    function () { alert('hi!'); }
);

試してみてください。 http://jsfiddle.net/bmArj/

これらのことを考慮すると、あなたが見ているスクリプトが他の方法で(あなたの質問に示されていないコードで)ブラウザの違いを考慮したのでない限りは、この部分の addEventListener は、IE のバージョンが 9 未満の場合、動作しないことがあります。

ドキュメントと関連する読み物