Я борюсь с управлением динамически построенными обработчиками событий в 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, и указать ряд уникальных атрибутов и действий, событий, только с один вызов функции для каждого. Опять же, это чрезвычайно упрощенный пример, просто чтобы продемонстрировать, о чем я говорю, в некоторых случаях с проектом, в котором я сейчас участвую, события могут включать в себя десятки строк, они могут даже делать динамические аякс-вызовы на основе пройденного параметром или другими динамически генерируемыми данными. В более крайних случаях я создаю таблицы, чьи отдельные строки/столбцы/ячейки могут нуждаться в обработке событий на основе динамически созданного содержимого обработчика или обработчика обработчика.
Первоначально я построил такие функции, как выше, как так:
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» и «dormantStyle» стало значением, используемым всеми обработчиками, созданными таким образом (вместо того, чтобы каждый из них сохранил свой собственный уникальный набор стилей, например). Именно это привело меня к использованию 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()»!
Спасибо!
Это кричит что-то вроде jQuery, но поскольку вы не хотите использовать сторонние библиотеки: ваше начальное решение (только с одним «eval») имеет гораздо больший смысл. Это 'activeStyle' и' dormantStyle' 'stick, вероятно, связано с контекстом, из которого вы вызываете 'createInput' (возможно, в' for' loop?), А не для самой функции. – robertklep