[解決済み] addEventListenerのforループと値渡し [重複].
質問
forループを使って複数のオブジェクトにイベントリスナーを追加しようとしているのですが、結局すべてのリスナーが同じオブジェクト --> をターゲットにしています。
インスタンスごとにboxaとboxbを定義してリスナーを手動で追加すると、それは動作します。私が期待した方法で動作していないのは、addEvent for-loop のせいだと思います。たぶん、私はまったく間違ったアプローチを使用しています。
class="container" の 4 つを使用した例です。 コンテナ 4 のトリガーは、想定どおりに動作します。 コンテナ 1、2、3 のトリガーは、コンテナ 4 のイベントをトリガーしますが、トリガーがすでにアクティブになっている場合のみです。
// Function to run on click:
function makeItHappen(elem, elem2) {
var el = document.getElementById(elem);
el.style.backgroundColor = "red";
var el2 = document.getElementById(elem2);
el2.style.backgroundColor = "blue";
}
// Autoloading function to add the listeners:
var elem = document.getElementsByClassName("triggerClass");
for (var i = 0; i < elem.length; i += 2) {
var k = i + 1;
var boxa = elem[i].parentNode.id;
var boxb = elem[k].parentNode.id;
elem[i].addEventListener("click", function() {
makeItHappen(boxa, boxb);
}, false);
elem[k].addEventListener("click", function() {
makeItHappen(boxb, boxa);
}, false);
}
<div class="container">
<div class="one" id="box1">
<p class="triggerClass">some text</p>
</div>
<div class="two" id="box2">
<p class="triggerClass">some text</p>
</div>
</div>
<div class="container">
<div class="one" id="box3">
<p class="triggerClass">some text</p>
</div>
<div class="two" id="box4">
<p class="triggerClass">some text</p>
</div>
</div>
どのように解決するのですか?
クロージャ! :D
この修正されたコードは、あなたの意図したとおりに動作します。
// Function to run on click:
function makeItHappen(elem, elem2) {
var el = document.getElementById(elem);
el.style.backgroundColor = "red";
var el2 = document.getElementById(elem2);
el2.style.backgroundColor = "blue";
}
// Autoloading function to add the listeners:
var elem = document.getElementsByClassName("triggerClass");
for (var i = 0; i < elem.length; i += 2) {
(function () {
var k = i + 1;
var boxa = elem[i].parentNode.id;
var boxb = elem[k].parentNode.id;
elem[i].addEventListener("click", function() { makeItHappen(boxa,boxb); }, false);
elem[k].addEventListener("click", function() { makeItHappen(boxb,boxa); }, false);
}()); // immediate invocation
}
<div class="container">
<div class="one" id="box1">
<p class="triggerClass">some text</p>
</div>
<div class="two" id="box2">
<p class="triggerClass">some text</p>
</div>
</div>
<div class="container">
<div class="one" id="box3">
<p class="triggerClass">some text</p>
</div>
<div class="two" id="box4">
<p class="triggerClass">some text</p>
</div>
</div>
なぜこれで直るのですか?
for(var i=0; i < elem.length; i+=2){
var k = i + 1;
var boxa = elem[i].parentNode.id;
var boxb = elem[k].parentNode.id;
elem[i].addEventListener("click", function(){makeItHappen(boxa,boxb);}, false);
elem[k].addEventListener("click", function(){makeItHappen(boxb,boxa);}, false);
}
は実際には非正規のJavaScriptです。このように解釈されます。
var i, k, boxa, boxb;
for(i=0; i < elem.length; i+=2){
k = i + 1;
boxa = elem[i].parentNode.id;
boxb = elem[k].parentNode.id;
elem[i].addEventListener("click", function(){makeItHappen(boxa,boxb);}, false);
elem[k].addEventListener("click", function(){makeItHappen(boxb,boxa);}, false);
}
なぜなら
変数浮動
を使用することができます。
var
の宣言はスコープの一番上に移動します。JavaScript にはブロックスコープがないので (
for
,
if
,
while
など) は関数の先頭に移動されます。
更新します。
ES6では
let
を使ってブロックスコープの変数を取得することができます。
あなたのコードが実行されると、次のようなことが起こります。
for
ループにクリック コールバックを追加し、さらに
boxa
を割り当てますが、その値は次の繰り返しで上書きされます。クリックイベントが発生すると、コールバックが実行されて
boxa
の値は
常に
であり、リストの最後の要素です。
クロージャを使う(値を閉じる
boxa
,
boxb
など)クリックハンドラのスコープに値をバインドします。
のようなコード解析ツールは JSLint または JSHint を使えば、このような怪しいコードをキャッチすることができます。もしあなたがたくさんのコードを書いているのなら、これらのツールの使い方を学ぶために時間をかける価値はあるでしょう。IDEによっては、これらのツールが組み込まれているものもあります。
関連
-
[解決済み] let "と "var "の使い分けは?
-
[解決済み] forEachループでasync/awaitを使用する
-
[解決済み] 配列の反復処理に "for...in "を使用するのは、なぜ良くないのでしょうか?
-
[解決済み] jQueryを使用してハイパーリンクのhref属性を変更する方法
-
[解決済み] Javaでenumを繰り返し処理するためのforループ
-
[解決済み] ( for... in ) と ( for... of ) の文の違いは何ですか?
-
[解決済み] JavaScriptのfor...of構文でループのカウンタ/インデックスを取得する
-
[解決済み] Reactコンポーネントでthis.setStateを複数回使用するとどうなりますか?
-
[解決済み] JSHintの'+'前の改行不良の説明
-
[解決済み] Fetch: ステータスがOKでない場合、プロミスを拒否し、エラーをキャッチするか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] ループ内のJavaScriptクロージャ - シンプルな実用例
-
[解決済み] 配列からオブジェクトを生成する
-
[解決済み] Google maps API V3 - 同一地点に複数のマーカーを設置する。
-
[解決済み] ExtJS 4のイベントハンドリングについて
-
[解決済み] JavaScriptでの大文字小文字を区別しない正規表現
-
[解決済み] AngularJS - ngRepeatフィルタリングされた結果の参照を取得する方法
-
[解決済み] ECMAScriptとは?
-
[解決済み] イテレータでmap()を使用する
-
[解決済み] Prototypeを使ってtextareaを自動サイズ調整するには?
-
[解決済み] JavaScriptでDIVを表示・非表示にするには?