Клуб API Карт

Нельзя удалить событие нажатия на карте

Пост в архиве.

Пример: https://tech.yandex.ru/maps/jsbox/2.1/event_properties

 

Если удалить подписку так: myMap.events.remove('click');

То событие никуда не пропадает.


Вот документация: https://tech.yandex.ru/maps/doc/jsapi/2.1/ref/reference/IEventManager-docpage/#remove


Что я делаю не так? 

10 комментариев

 

  документация: https://tech.yandex.ru/maps/doc/jsapi/2.1/ref/reference/IEventManager-docpage/#remove

  

 

Надо передавать ссылку на удаляемый обработчик вторым параметром
callback* —
Тип: Function
Функция-обработчик события. В качестве параметра в функцию передается объект события IEvent.

map.events.add('click', function(){ alert(); });

map.events.remove('click');

После этого по нажатию на карту все равно выскакивает alert.

 

Что изменить?

И можно просто удалить все подписки на click у map?

 

p.s. Вряд ли возможно найти более неудобный способ управления событиями.

Всеволод Шмыров
27 января 2016, 23:32
Доброе утро! Чтобы удалить событие, необходимо передать, как и в add, функцию-слушатель и контекст исполнения. Об этом можно почитать в нашей документации
https://tech.yandex.ru/maps/doc/jsapi/2.1/ref/reference/IEventManager-docpage/
https://tech.yandex.ru/maps/doc/jsapi/2.1/ref/reference/event.Manager-docpage/
Для упрощения можно использовать группу.
var handler = map.events.group()
.add('click', function(){ alert(); });
// ...
handler.removeAll();

Наша система событий не сложнее нативной подписки на события http://javascript.ru/tutorial/events/comparison.
jQuery замечательная библиотека, но все же её не очень удобно использовать для большинства задач.

Спасибо! Сработал именно ваш метод!

Вот так не работало:

map.events.add('click', this.addVertex.bind(this)); 
map.events.remove('click', this.addVertex.bind(this));  


А вот так все заработало: 
map.events.group().add('click', this.addVertex.bind(this)); 
map.events.group().removeAll(); 
Похоже что ваш API плохо работает с контекстами.
Всеволод Шмыров
27 января 2016, 23:32
API работает с контекстами корректно. Функция bind создает новую функцию привязанную к контексту. Каждый вызов this.addVertex.bind(this) порождает новую функцию. Соответственно ваш верхний код работает некорректно, так как вы передаете в remove функцию, которая ранее не была добавлена. Более подробно про функцию bind можно почитать здесь.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

Функция bind не работает в некоторых старых браузерах. Поэтому мы и предусмотрели явную передачу контекста. Это работающий пример
map.events.add('click', this.addVertex, this); 
map.events.remove('click', this.addVertex, this);

Ваш второй код тоже работает некорректно, так как функция group тоже порождает новую группу. Вам нужно записать группу в переменную, а потом вызвать removeAll у нее. Про переменные можно почитать здесь http://learn.javascript.ru/variables

Группу занес в переменную изначально. Просто тут писал чтобы быстрее. Поэтому все и работало. :)

С bind, получается, можно так:

var fn = this.addVertex.bind(this);
map.events.add('click', fn); 

map.events.remove('click', fn);  

 

function onClick(){ alert(); }

map.events.add('click', onClick);

map.events.remove('click', onClick);

 

И можно просто удалить все подписки на click у map?

Удалить все подписки это, на наш взгляд, плохой паттерн. Надо удалять только свои подписки, которые вы сами создали и контроллируете.

 

Удалять несколько подписок можно через группу

Спасибо, на счет группы не знал, нужно попробовать.

Кстати у меня удаление происходит не в том же контексте. И из за этого приходится делать так:

map.events.add( 'click', instance.onClick.bind(this) );

map.events.remove( 'click', instance.onClick.bind(this) );

 

В этом случае подписка не удаляется.

Кстати все подписки можно удалить так:
map.events.group().events.types.click = undefined;

Очень быстро и всего одна строка кода. ) 

Sergey Konstantinov
27 января 2016, 23:32
Расскажите, пожалуйста, а что по-вашему обозначает звёздочка "обязательный параметр" рядом с описанием параметра callback?