javascript で動的に構築されたイベント ハンドラーの管理に苦労しています。
いくつかの場所で、特定のイベント (主にマウスオーバー、マウスアウト、クリック) を処理する必要があるフォームまたはコントロールを作成しています。
秘訣は、多くの場合、イベント ハンドラー自体が、フォームまたはコントロールを構築する関数によって生成されるか、関数に渡されるデータを組み込む必要があることです。
そのため、「eval()」を使用してイベントを構築し、適切なデータを組み込んでいますが、これはある程度うまく機能しています。
問題は、「eval() を使うべきではない!」のようなものを見たり聞いたりし続けることです。動的に構築されたイベント ハンドラーが他のイベント ハンドラーを動的に構築する必要があり、ネストされた eval がかなり鈍い (穏やかに言えば) いくつかのますます醜い実装と同様に。
だから私はここにいて、誰かが私にもっと良い方法を教えてくれるかどうか尋ねています (ネイティブの JavaScript のみでお願いします。私はサードパーティのライブラリを実装していません!)。
私が話していることを説明するための大まかな例を次に示します。
function CreateInput(controlName,type,activeStyle,dormantStyle,whenClicked)
{
var inp = document.createElement('input');
inp.id = controlName;
inp.type = type;
inp.style.cssText = dormantStyle;
eval("inp.onfocus = function() { this.style.cssText = '" + activeStyle + "'; }");
eval("inp.onblur = function() { this.style.cssText = '" + dormantStyle + "'; }");
eval("inp.onclick = function() { " + whenClicked + "; }");
return inp;
}
この関数を使用すると、多数の異なる INPUT タグを簡単に作成し、多数の一意の属性とイベント アクションを指定できます。それぞれに対して関数を 1 回呼び出すだけです。繰り返しますが、これは非常に単純化された例です。私が話していることを示すためだけに、私が現在取り組んでいるプロジェクトでは、場合によっては、イベントに数十行を組み込むことができ、渡されたパラメータまたはその他の動的に生成されたデータ。より極端なケースでは、ハンドラーまたはハンドラーのハンドラーの動的に生成されたコンテンツに基づいて、個々の行/列/セルがイベントを処理する必要があるテーブルを作成します。
最初は、上記のような関数を次のように作成しました。
function CreateInput(controlName,type,activeStyle,dormantStyle,whenClicked)
{
var inp = document.createElement('input');
inp.id = controlName;
inp.type = type;
inp.style.cssText = dormantStyle;
inp.onfocus = function() { this.style.cssText = activeStyle; };
inp.onblur = function() { this.style.cssText = dormantStyle; };
eval("inp.onclick = function() { " + whenClicked + "; }");
return inp;
}
...しかし、「activeStyle」に最後に割り当てられた値が何であれ、「domantStyle」が、作成されたすべてのハンドラーで使用される値になることがわかりました (たとえば、それぞれが独自のスタイルのセットを保持するのではなく)。それが、関数が作成されたときに eval() を使用して変数の値を「ロックイン」するようになった理由ですが、これにより、次のような悪夢に陥りました。
(これは、私が現在取り組んでおり、ネストされた eval() 関数を使用する動的に構築されたイベント ハンドラーのサンプルです):
eval("input.onkeyup = function() { " +
"InputParse(this,'ucwords'); " +
"var tId = '" + myName + This.nodeName + "SearchTable" + uidNo + "'; " +
"var table = document.getElementById(tId); " +
"if (this.value.length>2) { " +
"var val = (this.value.indexOf(',') >=0 ) ? this.value.substr(0,this.value.indexOf(',')) : this.value; " +
"var search = Global.LoadData('?fn=citySearch&limit=3&value=' + encodeURI(val)); " +
"if (table) { " +
"while (table.rows.length>0) { table.deleteRow(0); } " +
"table.style.display='block'; " +
"} else { " +
"table = document.createElement('table'); " +
"table.id = tId; " +
"ApplyStyleString('" + baseStyle + ";position=absolute;top=20px;left=0px;display=block;border=1px solid black;backgroundColor=rgba(224,224,224,0.90);zIndex=1000;',table); " +
"var div = document.getElementById('" + divName + "'); " +
"if (div) { div.appendChild(table); } " +
"} " +
"if (search.rowCount()>0) { " +
"for (var i=0; i<search.rowCount(); i++) { " +
"var tr = document.createElement('tr'); " +
"tr.id = 'SearchRow' + i + '" + uidNo + "'; " +
"tr.onmouseover = function() { ApplyStyleString('cursor=pointer;color=yellow;backgroundColor=rgba(40,40,40,0.90);',this); }; " +
"tr.onmouseout = function() { ApplyStyleString('cursor=default;color=black;backgroundColor=rgba(224,224,224,0.90);',this); }; " +
"eval(\"tr.onclick = function() { " +
"function set(id,value) { " +
"var o = document.getElementById(id); " +
"if (o && o.value) { o.value = value; } else { alert('Could not find ' + id); } " +
"} " +
"set('" + myName + This.nodeName + "CityId" + uidNo + "','\" + search.id(i)+ \"'); " +
"set('" + myName + This.nodeName + "ProvId" + uidNo + "','\" + search.provId(i)+ \"'); " +
"set('" + myName + This.nodeName + "CountryId" + uidNo + "','\" + search.countryId(i) + \"'); " +
"set('" + input.id + "','\" + search.name(i)+ \"'); " +
"}\"); " +
"var td = document.createElement('td'); " +
"var re = new RegExp('('+val+')', 'gi'); " +
"td.innerHTML = search.name(i).replace(re,'<span style=\"font-weight:bold;\">$1</span>') + ', ' + search.provinceName(i) + ', ' + search.countryName(i); " +
"tr.appendChild(td); " +
"table.appendChild(tr); " +
"} " +
"} else { " +
"var tr = document.createElement('tr'); " +
"var td = document.createElement('td'); " +
"td.innerHTML = 'No matches found...';" +
"tr.appendChild(td); " +
"table.appendChild(tr); " +
"} " +
"} else { " +
"if (table) table.style.display = 'none'; " +
"} " +
"} ");
現在、「.onclick」イベントをテーブル行にバインドするためにネストされた eval() を取得する際に問題が発生しています。理由)...だから、「eval()」ステートメントの恐ろしい使用を避けながら、これらの同じ目標を達成できる方向に誰かが私を向けることができれば、本当に感謝しています!
ありがとう!