回答編集履歴

3

jQuery の event\.data がイベント定義する要素の数だけイベントハンドラを新しく生成していた問題に対処

2017/03/07 05:30

投稿

think49
think49

スコア18164

test CHANGED
@@ -118,7 +118,7 @@
118
118
 
119
119
 
120
120
 
121
- - [for文内でイベントハンドラを定義する (jQuery event.data版) - JSFiddle](https://jsfiddle.net/qg9cf4de/3/)
121
+ - [for文内でイベントハンドラを定義する (jQuery event.data版) - JSFiddle](https://jsfiddle.net/qg9cf4de/4/)
122
122
 
123
123
 
124
124
 
@@ -126,13 +126,17 @@
126
126
 
127
127
  'use strict';
128
128
 
129
+ function handleClick (event) {
130
+
131
+ event.data.parent.after('<img src="../img/img/img" width="100" height="30" alt="content" />');
132
+
133
+ }
134
+
135
+
136
+
129
137
  for (var i = 1; i < 6; ++i) {
130
138
 
131
- jQuery('#show-image-child-' + i).on('click', {parent: jQuery('.show-image-parent-' + i)}, function (event) {
139
+ jQuery('#show-image-child-' + i).on('click', {parent: jQuery('.show-image-parent-' + i)}, handleClick);
132
-
133
- event.data.parent.after('<img src="../img/img/img" width="100" height="30" alt="content" />');
134
-
135
- });
136
140
 
137
141
  }
138
142
 

2

typo修正

2017/03/07 05:30

投稿

think49
think49

スコア18164

test CHANGED
@@ -110,12 +110,6 @@
110
110
 
111
111
  });
112
112
 
113
- ('click', function (event) {
114
-
115
- jQuery('.' + event.currentTarget.id.replace(/-child(?=-)/, '-parent')).after('<img src="../img/img/img" width="100" height="30" alt="content" />');
116
-
117
- });
118
-
119
113
  ```
120
114
 
121
115
 

1

対策コード\(4点\)を追記

2017/03/07 05:25

投稿

think49
think49

スコア18164

test CHANGED
@@ -1,3 +1,7 @@
1
+ ### 原因
2
+
3
+
4
+
1
5
  `for` 文中でイベントハンドラ関数を定義した場合、外のスコープの変数はイベントハンドラが実行された時の値になります。
2
6
 
3
7
  イベントハンドラが実行されたタイミングでは for ループは終了していますので、仮に `numberOfQuestions === 5` であった場合、どのチェックボタンをクリックしても下記コードのように `.v4` に対してimg要素ノードが挿入されることになります。
@@ -26,4 +30,120 @@
26
30
 
27
31
 
28
32
 
33
+ ### [対策1] イベントハンドラ関数内で対象を算出する
34
+
35
+
36
+
37
+ - [for文内でイベントハンドラを定義する - JSFiddle](https://jsfiddle.net/qg9cf4de/)
38
+
39
+
40
+
41
+ ```JavaScript
42
+
43
+ 'use strict';
44
+
45
+ jQuery('[id^="show-image-child-"').on('click', function (event) {
46
+
47
+ jQuery('.' + event.currentTarget.id.replace(/-child(?=-)/, '-parent')).after('<img src="../img/img/img" width="100" height="30" alt="content" />');
48
+
49
+ });
50
+
51
+ ```
52
+
53
+
54
+
55
+ ### [対策2] addEventListener の listener オブジェクトに閉じ込める
56
+
57
+
58
+
59
+ - [for文内でイベントハンドラを定義する (addEventListener版) - JSFiddle](https://jsfiddle.net/qg9cf4de/1/)
60
+
61
+
62
+
63
+ ```JavaScript
64
+
65
+ 'use strict';
66
+
67
+ document.querySelectorAll('[id^="show-image-child-"').forEach(function (input) {
68
+
69
+ input.addEventListener('click', {
70
+
71
+ parent: jQuery('.' + input.id.replace(/-child(?=-)/, '-parent')),
72
+
73
+ handleEvent: function handleClick () {
74
+
75
+ this.parent.after('<img src="../img/img/img" width="100" height="30" alt="content" />');
76
+
77
+ }
78
+
79
+ }, false);
80
+
81
+ });
82
+
83
+ ```
84
+
85
+
86
+
87
+ ### [対策3] クロージャに閉じ込める
88
+
89
+
90
+
91
+ - [for文内でイベントハンドラを定義する (クロージャ版) - JSFiddle](https://jsfiddle.net/qg9cf4de/2/)
92
+
93
+
94
+
95
+ ```JavaScript
96
+
97
+ 'use strict';
98
+
99
+ jQuery('[id^="show-image-child-"').each(function (i, input) {
100
+
101
+ var parent = jQuery('.' + input.id.replace(/-child(?=-)/, '-parent'));
102
+
103
+
104
+
105
+ jQuery(input).on('click', function () {
106
+
107
+ parent.after('<img src="../img/img/img" width="100" height="30" alt="content" />');
108
+
109
+ });
110
+
111
+ });
112
+
113
+ ('click', function (event) {
114
+
115
+ jQuery('.' + event.currentTarget.id.replace(/-child(?=-)/, '-parent')).after('<img src="../img/img/img" width="100" height="30" alt="content" />');
116
+
117
+ });
118
+
119
+ ```
120
+
121
+
122
+
123
+ ### [対策4] jQuery の event.data に閉じ込める
124
+
125
+
126
+
127
+ - [for文内でイベントハンドラを定義する (jQuery event.data版) - JSFiddle](https://jsfiddle.net/qg9cf4de/3/)
128
+
129
+
130
+
131
+ ```JavaScript
132
+
133
+ 'use strict';
134
+
135
+ for (var i = 1; i < 6; ++i) {
136
+
137
+ jQuery('#show-image-child-' + i).on('click', {parent: jQuery('.show-image-parent-' + i)}, function (event) {
138
+
139
+ event.data.parent.after('<img src="../img/img/img" width="100" height="30" alt="content" />');
140
+
141
+ });
142
+
143
+ }
144
+
145
+ ```
146
+
147
+
148
+
29
149
  Re: tmng さん