Пользовательский прослушиватель событий JavaScript
Мне было интересно, может ли кто-нибудь помочь мне понять, как именно создавать различные пользовательские прослушиватели событий.
У меня нет конкретного случая события, но я хочу узнать только в общих чертах, как это делается, чтобы я мог применить его там, где это необходимо.То, что я хотел сделать, просто чтобы некоторые люди могли знать, было:
var position = 0;
for(var i = 0; i < 10; i++)
{
position++;
if((position + 1) % 4 == 0)
{
// do some functions
}
}
4 ответа:
var evt = document.createEvent("Event"); evt.initEvent("myEvent",true,true); // custom param evt.foo = "bar"; //register document.addEventListener("myEvent",myEventHandler,false); //invoke document.dispatchEvent(evt);
Вот способ сделать это более локально, точно определяя слушателей и издателей: http://www.kaizou.org/2010/03/generating-custom-javascript-events/
Реализовать пользовательские события несложно. Вы можете реализовать его многими способами. В последнее время я делаю это так:
Наблюдаемый объект может быть повторно использован и применен любым конструктором, которому он нужен, просто смешав прототип наблюдаемого с прототипом этого конструктора./*************************************************************** * * Observable * ***************************************************************/ var Observable; (Observable = function() { }).prototype = { listen: function(type, method, scope, context) { var listeners, handlers; if (!(listeners = this.listeners)) { listeners = this.listeners = {}; } if (!(handlers = listeners[type])){ handlers = listeners[type] = []; } scope = (scope ? scope : window); handlers.push({ method: method, scope: scope, context: (context ? context : scope) }); }, fireEvent: function(type, data, context) { var listeners, handlers, i, n, handler, scope; if (!(listeners = this.listeners)) { return; } if (!(handlers = listeners[type])){ return; } for (i = 0, n = handlers.length; i < n; i++){ handler = handlers[i]; if (typeof(context)!=="undefined" && context !== handler.context) continue; if (handler.method.call( handler.scope, this, type, data )===false) { return false; } } return true; } };
Чтобы начать слушать, вы должны зарегистрировать себя в наблюдаемом объекте, например:
var obs = new Observable(); obs.listen("myEvent", function(observable, eventType, data){ //handle myEvent });
Или если ваш слушатель является методом объекта, например:
obs.listen("myEvent", listener.handler, listener);
Где слушатель является экземпляром объекта, реализующего метод "обработчик".
Наблюдаемый объект теперь может вызывать свой метод fireEvent всякий раз, когда происходит что-то, что он хочет сообщить своим слушателям:this.fireEvent("myEvent", data);
Где данные-это некоторые данные, которые слушатели мои находят интересными. Что бы вы там ни поместили, это зависит от вас - вы лучше знаете, из чего состоит ваше пользовательское событие.
Метод fireEvent просто проходит через все прослушиватели, зарегистрированные для "myEvent", и вызывает зарегистрированную функцию. Если функция возвращает false, то это означает, что событие отменяется, и наблюдаемое не будет вызывать другие прослушиватели. В результате весь метод fireEvent также вернет fasle, так что наблюдаемый знает, что любое действие, о котором он уведомлял своих слушателей, теперь должно быть откатано.
Возможно, это решение подходит не всем, но я получил много пользы от этого относительно простого куска кода.
Отсюда:
Https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events
// create the event var evt = document.createEvent('Event'); // define that the event name is `build` evt.initEvent('build', true, true); // elem is any element elem.dispatchEvent(evt); // later on.. binding to that event // we'll bind to the document for the event delegation style. document.addEventListener('build', function(e){ // e.target matches the elem from above }, false);
Вот действительно простая (машинописная/Вавилонская) реализация:
const simpleEvent = <T extends Function>(context = null) => { let cbs: T[] = []; return { addListener: (cb: T) => { cbs.push(cb); }, removeListener: (cb: T) => { let i = cbs.indexOf(cb); cbs.splice(i, Math.max(i, 0)); }, trigger: (<T> (((...args) => cbs.forEach(cb => cb.apply(context, args))) as any)) }; };
Вы используете его так:
let onMyEvent = simpleEvent(); let listener = (test) => { console.log("triggered", test); }; onMyEvent.addListener(listener); onMyEvent.trigger("hello"); onMyEvent.removeListener(listener);
Или в классах, подобных этому
class Example { public onMyEvent = simpleEvent(this); }
Если вы хотите простой JavaScript, вы можете транспилировать его с помощьюTypeScript playground .