Событие маркера листовки срабатывает в неподходящее время

Я работаю с листовкой (v 0.7.7), и у меня есть вызов Ajax, который получает некоторые данные сервера для привязки к моей карте в виде интерактивных текстовых меток. В цикле, где я связываю данные JSON, полученные с сервера, у меня есть следующий код:

var item_name = L.marker([data.X, data.Y],
{
    icon: L.divIcon(
    {
        className:'MapTag', 
        iconAnchor: [10, 10],
        html:'<img src="/Images/Map/Item' + data.Id + '.png">' + data.Name 
    })
}).on('click', onItemClick(data.Id));

item_layer.addLayer(item_name);

В другом месте у меня есть код onItemClick:

function onItemClick(item_id)
{
    alert(item_id);
}

Теперь хорошие новости: если я закомментирую часть привязки событий, цикл завершится, и листовка будет вести себя так, как должна. Однако, когда я привязываю событие click, все становится странным. Событие запускается один раз для каждого элемента в коллекции, к которой я привязан. Когда данные загружаются с сервера, я получаю всплывающее предупреждение каждый раз в цикле с идентификатором текущего элемента. Такое ощущение, что он запускается «onload», а не «onclick». В довершение всего, он также не регистрирует щелчки по divIcons после загрузки.

Здесь должно быть что-то, чего мне не хватает, но я не могу понять, что именно. Какие-либо предложения?

Этот вопрос похож на (Маркер в листовке, событие щелчка)

Решение: я изменил последнюю строку объявления divIcon на:

}).on('click', function(e){ alert(data.Id); });

Теперь это работает, как задумано. Я предполагаю, что странное поведение привязки является результатом отсутствия привязки ссылки на определенный метод и листовки, имеющей своего рода функциональный сбой в своем коде управления событиями.

Я сохранил аргумент «e», так как это то, что показывают документы листовки. Я не использую его, но если кто-то другой скопирует это, ему это может понадобиться.


person Roger Hill    schedule 16.02.2016    source источник


Ответы (1)


Вы путаете концепции ссылок на функции и вызовов функций и не создаете замыкание идентификатора элемента.

Если вы объявите это:

function onItemClick(id) { alert(id); }

Это печатает ссылку на функцию:

console.log( onItemClick );

И это печатает возвращаемое значение вызова этой функции (поскольку она ничего не возвращает, это равно undefined):

console.log( onItemClick(5) );

Итак, когда вы делаете это:

L.marker(....).on('click', onItemClick(id) );

функция вызывается, и on() получает возвращаемое значение этой функции, т.е.:

L.marker(....).on('click', undefined );

Что вам нужно сделать, так это иметь функцию, которая возвращает функцию:

function onItemClick(id) { return function(){ alert(id); } }

Таким образом, когда вы делаете

L.marker(....).on('click', onItemClick(5) );

Это вызовет функцию и использует возвращаемое значение, которое теперь выглядит так:

L.marker(....).on('click', function() { alert(5); } );
person IvanSanchez    schedule 16.02.2016
comment
Вау, с ума сошел. Я смотрел на него пару часов, и ты пришел и прибил его. Спасибо за помощь. - person Roger Hill; 16.02.2016
comment
Я только что заметил кое-что. Поскольку функция, которую мы сопоставляем с событием щелчка, является замыканием, когда я помещаю этот код в цикл, все элементы сопоставляются с одним и тем же идентификатором. (Все элементы смотрят на идентификатор, который после завершения цикла является последним идентификатором). Я пытался записать вызов функции в виде строки для тега, чтобы каждый тег листовки не содержал ссылку на одно и то же значение. Мне нужно переосмыслить это. - person Roger Hill; 17.02.2016
comment
Нет - цель закрытия состоит в том, чтобы предотвратить именно это, определив собственную переменную область видимости. Я рекомендую вам прочитать документацию о замыканиях — я знаю, что их сложно освоить. - person IvanSanchez; 17.02.2016