Удаление прослушивателя событий, который был добавлен с помощью bind
в JavaScript, каков наилучший способ удалить функцию, добавленную в качестве прослушивателя событий с помощью bind ()?
пример
(function(){
// constructor
MyClass = function() {
this.myButton = document.getElementById("myButtonID");
this.myButton.addEventListener("click", this.clickListener.bind(this));
};
MyClass.prototype.clickListener = function(event) {
console.log(this); // must be MyClass
};
// public method
MyClass.prototype.disableButton = function() {
this.myButton.removeEventListener("click", ___________);
};
})();
единственный способ, который я могу придумать, - это отслеживать каждого слушателя, добавленного с помощью bind.
выше пример с этим методом:
(function(){
// constructor
MyClass = function() {
this.myButton = document.getElementById("myButtonID");
this.clickListenerBind = this.clickListener.bind(this);
this.myButton.addEventListener("click", this.clickListenerBind);
};
MyClass.prototype.clickListener = function(event) {
console.log(this); // must be MyClass
};
// public method
MyClass.prototype.disableButton = function() {
this.myButton.removeEventListener("click", this.clickListenerBind);
};
})();
есть ли лучшие способы сделать это?
8 ответов:
хотя то, что сказал @machineghost, было правдой, что события добавляются и удаляются одинаково, недостающая часть уравнения была такой:
новая ссылка на функцию создается после
.bind()
называется!посмотреть bind () изменяет ссылку на функцию? | Как установить постоянно?
Итак, чтобы добавить или удалить его, назначьте ссылку на переменную:
var x = this.myListener.bind(this); Toolbox.addListener(window, 'scroll', x); Toolbox.removeListener(window, 'scroll', x);
это работает, как ожидалось для меня.
для тех, у кого есть эта проблема при регистрации/удалении прослушивателя компонента React в/из Flux store, добавьте следующие строки в конструктор вашего компонента:
class App extends React.Component { constructor(props){ super(props); // it's a trick! needed in order to overcome the remove event listener this.onChange = this.onChange.bind(this); } // then as regular... componentDidMount (){ AppStore.addChangeListener(this.onChange); } componentWillUnmount (){ AppStore.removeChangeListener(this.onChange); } onChange () { let state = AppStore.getState(); this.setState(state); } render() { // ... } }
не имеет значения, используете ли вы связанную функцию или нет; вы удаляете ее так же, как и любой другой обработчик событий. Если ваша проблема заключается в том, что связанная версия является своей собственной уникальной функцией, вы можете либо отслеживать связанные версии, либо использовать
removeEventListener
подпись, которая не принимает определенный обработчик (хотя, конечно, это удалит другие обработчики событий того же типа).(в качестве примечания,
addEventListener
не работает во всех браузерах; вы действительно должны использовать библиотеку как jQuery, чтобы сделать ваши подключения событий в кросс-браузер способ для вас. Кроме того, jQuery имеет концепцию событий пространства имен, которые позволяют привязать к "click.foo"; когда вы хотите удалить событие, вы можете сказать jQuery" удалить все события foo " без необходимости знать конкретный обработчик или удалять другие обработчики.)
вот решение:
var o = { list: [1, 2, 3, 4], add: function () { var b = document.getElementsByTagName('body')[0]; b.addEventListener('click', this._onClick()); }, remove: function () { var b = document.getElementsByTagName('body')[0]; b.removeEventListener('click', this._onClick()); }, _onClick: function () { this.clickFn = this.clickFn || this._showLog.bind(this); return this.clickFn; }, _showLog: function (e) { console.log('click', this.list, e); } }; // Example to test the solution o.add(); setTimeout(function () { console.log('setTimeout'); o.remove(); }, 5000);
решение jQuery:
let object = new ClassName(); let $elem = $('selector'); $elem.on('click', $.proxy(object.method, object)); $elem.off('click', $.proxy(object.method, object));
Если вы хотите использовать 'onclick', как было предложено выше, вы можете попробовать это:
(function(){ var singleton = {}; singleton = new function() { this.myButton = document.getElementById("myButtonID"); this.myButton.onclick = function() { singleton.clickListener(); }; } singleton.clickListener = function() { console.log(this); // I also know who I am }; // public function singleton.disableButton = function() { this.myButton.onclick = ""; }; })();
Я надеюсь, что это помогает.
это 2016 год, и стандарт DOM не очень помог в решении довольно распространенной проблемы, с которой мы сталкиваемся время от времени. да единственный способ удалить обработчик ограниченного события-сохранить ссылку на ограниченную функцию и использовать ее в removeEventListener, как указано в других решениях здесь.
однако, когда у вас есть много слушателей, это становится грязным. Никто не придумал простых функций, которые абстрагируют работу по сохранению ссылок на ограниченные функции. Я придумал две функции с именами on () и off () (jQuery inspired names), которые я добавил ко всем HTMLElements, добавив его в прототип. код. (Работает только на IE 11+, так как он использует WeakMap)
таким образом, используя это, вы можете добавить прослушиватели событий и удалить их следующим образом:
this.myButton.on('click', this.clickListener, this); this.myButton.off('click', this.clickListener, this); //yup, it's removed
деталей реализации и принятых решений много, поэтому я не буду это объяснять:)
Если вам не нравится добавлять функции в собственные объекты, то вы можете добиться этого, немного отредактировав мой код. (Но серьезно, стандарт DOM должен был добавить некоторый API, чтобы решить это для нас в первую очередь).
Это было некоторое время, но MDN имеет супер объяснение по этому поводу. Это помогло мне больше, чем здесь.
MDN:: EventTarget.addEventListener-значение "this" в обработчике
это дает отличную альтернативу функции handleEvent.
Это пример с и без привязки:
var Something = function(element) { this.name = 'Something Good'; this.onclick1 = function(event) { console.log(this.name); // undefined, as this is the element }; this.onclick2 = function(event) { console.log(this.name); // 'Something Good', as this is the binded Something object }; element.addEventListener('click', this.onclick1, false); element.addEventListener('click', this.onclick2.bind(this), false); // Trick }
проблема в приведенном выше примере заключается в том, что вы не можете удалить прослушиватель с помощью bind. Другое решение заключается в использовании специального функция называется handleEvent, чтобы поймать любые события: