我正在努力在 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 标记并指定许多独特的属性和事件操作,每个只需一个函数调用。同样,这是一个非常简化的示例,只是为了演示我在说什么,在某些情况下,在我目前正在进行的项目中,事件可以包含几十行,它们甚至可能基于传递的动态 ajax 调用参数或其他动态生成的数据。在更极端的情况下,我构建表格,其各个行/列/单元格可能需要根据处理程序的动态生成内容或处理程序的处理程序来处理事件。
最初,我已经构建了像上面这样的函数:
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”和“休眠样式”都成为所有由此创建的处理程序使用的值(例如,而不是每个处理程序都保留自己独特的一组样式)。这就是导致我在创建函数时使用 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'; " +
"} " +
"} ");
目前,我在让嵌套的 eval() 将“.onclick”事件绑定到表格行时遇到问题,并且,正如您所看到的,弄清楚代码变得非常麻烦(调试也是所有已知的原因)......所以,如果有人能指出我能够实现这些相同目标的方向,同时避免可怕地使用“eval()”语句,我将非常感激!
谢谢!