2015-06-30 2 views
2

Я создал конструктор, который будет обрабатывать пользовательский элемент управления списком. Я создал метод, чтобы позволить пользователю добавлять элементы в список, и мне нужно назначить обработчики событий событиям щелчка элементов списка (div).Javascript: назначить onclick внутри класса

Упрощенная версия кода находится здесь. Элементы списка создаются с использованием свойства innerHTML и шаблона строки, на котором я заменяю определенные части. Позже я получить элемент по его идентификатору и присвоить ему функцию закрытия:

function prueba(){ 
    var plantilla = '<div id="«id»">«texto»</div>'; 

    var f = function(nombre){ 
     return function(){console.log('mi nombre es ' + nombre)}; 
    }; 

    this.agregar = function(id, texto){ 
     var tmp = plantilla.replace('«id»', id); 
     tmp = tmp.replace('«texto»', texto); 
     document.body.innerHTML += tmp; 

     document.getElementById(id).onclick = f(id); 
    }; 
}; 

Проблема заключается в том, что, по-видимому, обработчик событий unasigned предыдущих созданных дивы, так только удерживается последним, так как его можно проверить при помощи нижеуказанного кода:

var p = new prueba; 

p.agregar('i1', 'texto1'); 
console.log(document.getElementById('i1').onclick.toString());//shows the function code 
p.agregar('i2', 'texto2'); 
console.log(document.getElementById('i2').onclick.toString());//shows the function code 
console.log(document.getElementById('i1').onclick.toString());//returns 'null' error 
p.agregar('i3', 'texto3'); 
console.log(document.getElementById('i3').onclick.toString());//shows the function code 
console.log(document.getElementById('i2').onclick.toString());//returns 'null' error 

Это происходит в Iceweasel, а также в Chromium. Это НЕ произойдет, когда я добавлю «onclick = f (« id »)» в шаблон (который я не могу сделать здесь из-за выделенной области функции), и это не происходит, если я использую document.createElement. Что я делаю не так?

ответ

1

Вы уничтожаете элементы ранее созданные, когда вы делаете это:

document.body.innerHTML += tmp; 

Вместо этого используйте insertAdjacentHMTL(), если вы хотите добавить, используя HTML-разметку.

document.body.insertAdjacentHTML("beforeend", tmp); 

Теперь вместо того, чтобы идти через этот разрушительный процесс ...

  1. сериализации существующие DOM узлы HTML
  2. сцепить новый фрагмент HTML в сериализованными узлы
  3. уничтожить старые узлы
  4. воссоздать узлы с новыми узлами

... он просто создает новое содержимое и помещает его перед закрытием элемента body.

В принципе, удалите element.innerHTML += ... из ваших правил кодирования. Это никогда не нужно, это неэффективно, и это вызывает проблемы, как то, что вы описали.


FYI, метод .insertAdjacentHTML() получает 4 возможности строку в качестве первого аргумента. Каждый из них обозначает позицию относительно элемента, на который вы его вызываете.

Струны ...

  • "beforebegin"
  • "afterbegin"
  • "beforeend"
  • "afterend"

этикетки довольно очевидны. Они позиционируют новое содержимое перед текущим элементом, внутри текущего элемента в начале, внутри текущего элемента в конце или после текущего элемента соответственно.


Ваш полный код будет выглядеть так, что я слишком укоротить немного, так как tmp действительно не нужен здесь:

function prueba(){ 
    var plantilla = '<div id="«id»">«texto»</div>'; 

    var f = function(nombre){ 
     return function(){console.log('mi nombre es ' + nombre)}; 
    }; 

    this.agregar = function(id, texto){ 
     document.body.insertAdjacentHTML("beforeend", 
              plantilla.replace('«id»', id) 
                 .replace('«texto»', texto)); 

     document.getElementById(id).onclick = f(id); 
    }; 
}; 
+0

insertAdjacentHTML действительно решает проблему, спасибо !. У меня есть еще одно сомнение: вы говорите, что это уничтожает ранее созданные элементы, но единственное, что уничтожено, - это назначенная им функция (я действительно вижу новые divs со своим соответствующим текстом). Является ли функция считанной новым элементом? –

+0

@CarlosPrieto: он уничтожает элементы, а также все, что связано с ними, например функции обработчика событий. Затем он воссоздает их. Это очень неэффективно. Скажем, что у вас есть всего 100 узлов DOM в 'body'. Что происходит, так это то, что движок JS должен проходить через * каждый * узел, преобразовывать их в строку HTML, добавлять новый HTML в конец этой строки, уничтожать старые узлы, анализировать только что созданный HTML, создавать новые узлы и положить их в «тело». Так что да, это в основном уничтожает их, а затем воссоздает их, что является расточительным. –

+0

... есть * могут быть некоторые оптимизации, чтобы сделать его несколько более эффективным, чем тот, но кто знает. Принцип разрушительный и определенно уничтожает обработчики событий и другие вещи, поэтому '.insertAdjacentHTML' помогает очень. –

Смежные вопросы