Tengo un problema con mi evento de vinculación, me gustaría eliminar cada evento cuando se activa el evento de cambio. Está funcionando bien sin un bucle.
this.objectInstance.on('selected', () => { document.querySelectorAll('select').forEach((el) => { this.test = this.fontFamilyHandler.bind(this, el.getAttribute('id')); el.addEventListener('change', this.test); }) }); this.objectInstance.on('deselected', () => { document.querySelectorAll('select').forEach((el) => { el.removeEventListener('change', this.test); }) }); fontFamilyHandler = (key, evt) => { this.objectInstance.set(key, evt.target.value); this.canvas.requestRenderAll(); }¿Tienes alguna idea de por qué no funciona?
En cada iteración, está sobrescribiendo this.test con el siguiente oyente. Entonces, al final, this.test contendrá el último oyente adjunto y, por lo tanto, solo puede eliminarlo.
Puedo ver dos soluciones aquí:
this.objectInstance.on('selected', () => { this.test = new WeakMap(); document.querySelectorAll('select').forEach((el) => { const handler = this.fontFamilyHandler.bind(this, el.getAttribute('id')); this.test.set(el, handler); el.addEventListener('change', handler); }) }); this.objectInstance.on('deselected', () => { document.querySelectorAll('select').forEach((el) => { if (!this.test.has(el)) continue; el.removeEventListener('change', this.test.get(el)); }) }); (Nota: usar solo una matriz no sería estable porque si cambia la cantidad de elementos <select> en el documento, los índices no estarían sincronizados).
(Nota: también funcionaría con Map en lugar de WeakMap , pero este último permite la recolección de elementos no utilizados antes de cualquier elemento <select> que se elimine del DOM).
<select> , lo que significa que el evento de change solo provendrá del propio <select> , ya que no puede tener ningún elemento secundario que pueda enviar eventos de change , usando event.target.id también funciona: const eventHandler = event => this.fontFamilyHandler(event.target.id, event); this.objectInstance.on('selected', () => { document.querySelectorAll('select').forEach((el) => { el.addEventListener('change', eventHandler); }) }); this.objectInstance.on('deselected', () => { document.querySelectorAll('select').forEach((el) => { el.removeEventListener('change', eventHandler); }) }); (Nota: el.id es más fácil que el.getAttribute('id') y hace lo mismo; consulte Element#id ).
fontFamilyHandler directamente y cambiarlo para leer el ID del elemento en sí. this.objectInstance.on('selected', () => { document.querySelectorAll('select').forEach((el) => { el.addEventListener('change', this.fontFamilyHandler); }) }); this.objectInstance.on('deselected', () => { document.querySelectorAll('select').forEach((el) => { el.removeEventListener('change', this.fontFamilyHandler); }) }); // I removed the `key` argument here this.fontFamilyHandler = evt => { this.objectInstance.set(evt.target.id, evt.target.value); this.canvas.requestRenderAll(); }Del comentario anterior...
"Uno necesita ver el código circundante para comprender el problema real con el
thislidiando el OP... Tengo especial curiosidad porfontFamilyHandler = (key, evt) => { /* ... */ }where esta función flota libremente frente a la línea 3 donde de repente se vethis.fontFamilyHandler.bind(this, el.getAttribute('id'));"
Hasta entonces, la siguiente respuesta proporcionada asume una especie de sintaxis/sistema de clase para una clase hipotética de MyType .
De causa la unión como con ...
this.fontFamilyHandler.bind(this, el.getAttribute('id')); ... no es necesario en absoluto porque el OP ya accede al event.target dentro de este controlador que es igual al anterior el ...
fontFamilyHandler = (key, evt) => { this.objectInstance.set(key, evt.target.value); this.canvas.requestRenderAll(); } Por lo tanto, no es necesario vincular la id de cada elemento, ya que se puede acceder a esta propiedad a través de evt.target.id tanto como al valor ya a través evt.target.value .
Al final, el código se reducirá a algo mucho más legible como...
//class MyType { // constructor() { // this.objectInstance = { on: () => {} }; this.objectInstance.on('selected', () => document .querySelectorAll('select') .forEach(el => el.addEventListener('change', this.fontFamilyHandler) ) ); this.objectInstance.on('deselected', () => document .querySelectorAll('select') .forEach(el => el.removeEventListener('change', this.fontFamilyHandler) ) ); this.fontFamilyHandler = ({ target }) => { this.objectInstance.set(target.id, target.value); this.canvas.requestRenderAll(); }; // } //}