Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

150
Visualizações
Cómo enviar eventos personalizados de Javascript desde un objeto personalizado

Tengo 2 scripts (ejemplos extremadamente simplificados a continuación): el primero controla la visualización de un menú de navegación específico en una página y se usa en varios lugares para diferentes tipos de menús.

 const NavMenu = function(selector) { this.menuItems = document.querySelectorAll(`${selector} li > a`); let This = this; This.menuItems.forEach(item => { item.addEventListener('click', e => { item.classList.toggle('selected'); }); }); } const myNavMenu = new NavMenu('.menu-wrap');

El otro se usa para 1 propósito específico en una página específica que contiene un menú controlado por el primer script.

 (function () { const menuItems = document.querySelectorAll('.menu-wrap li > a'); menuItems.forEach(item => { item.addEventListener('click', e => { const selectedItems = document.querySelectorAll('.menu-wrap li > a.selected'); let str = ''; if(selectedItems.length) { selectedItems.forEach((item, i) => { str += `${item.textContent} `; }); document.querySelector('#results').innerText = `Selected: ${str}`; } }); }); })();

Como puede ver, la segunda secuencia de comandos tiene un controlador de clics que realiza una acción según el estado de cada elemento del menú ("seleccionado" o no). Dado que ese estado lo establece el primer script, esto solo funciona si el controlador de clics del primer script se ejecuta ANTES del segundo.

Creé una versión en la que fuerzo al controlador de clics del segundo script para que se ejecute primero (a través setTimeout ). Al hacer clic en los elementos, puede ver que el texto resultante no coincide. https://codepen.io/daveh0/pen/GROXmrq

Debido a que el primer script se usa en muchos otros lugares, debe ejecutarse independientemente de cualquier otro script; de lo contrario, simplemente habría combinado el 2.

Creo que un evento personalizado es la respuesta aquí. Implementé uno aquí: https://codepen.io/daveh0/pen/xxPaqzJ de un ejemplo que encontré, pero no tengo idea si esta es la forma correcta de hacerlo. Funciona, pero eso no significa mucho...

Creo que el evento debería estar vinculado de alguna manera al objeto NavMenu , pero no pude hacer que se enviara desde otra cosa que no sea window , un document u otro elemento DOM. ¿Alguien puede indicarme la dirección correcta para saber cómo puedo hacer algo como: myMenu.addEventListener('done', e => //do some stuff) en lugar de tenerlo adjunto a la window ? O si estoy muy lejos para empezar, siéntete libre de hacérmelo saber también.

Sé que esto está integrado en jQuery, pero debe permanecer como Vanilla JavaScript, ¡gracias!

about 4 years ago · Juan Pablo Isaza
1 Respostas
Responde à pergunta

0

Terminé usando una clase de emisor de eventos que encontré (y de la que aprendí mucho) en este artículo . Como dijo @Bergi en un comentario sobre el OP, los eventos no se pueden adjuntar a un objeto simple. Dado que el Script 1 se puede usar en cualquier lugar y en todas las situaciones diferentes, me pareció lo más estándar y lógico.

Es súper sencillo...

  1. Cree una instancia del emisor en el Script 1:
    This.emitter = new MyEventEmitter();

  2. Emita eventos donde sea necesario con cualquier dato que sea apropiado (en el Script 1): This.emitter.emit("done", item);

  3. "Escuche" el evento y manéjelo apropiadamente en el Script 2:
    NavMenu.emitter.on("done", menuItem => {...});


Aquí está todo lo que puede ver funcionando en este Codepen .

 class MyEventEmitter { constructor() { this._events = {}; } on(name, listener) { if (!this._events[name]) { this._events[name] = []; } this._events[name].push(listener); } removeListener(name, listenerToRemove) { if (!this._events[name]) { throw new Error( `Can't remove a listener. Event "${name}" doesn't exits.` ); } const filterListeners = (listener) => listener !== listenerToRemove; this._events[name] = this._events[name].filter(filterListeners); } emit(name, data) { if (!this._events[name]) { throw new Error(`Can't emit an event. Event "${name}" doesn't exits.`); } const fireCallbacks = (callback) => { callback(data); }; this._events[name].forEach(fireCallbacks); } } const NavMenu = function (selector) { this.menuItems = document.querySelectorAll(`${selector} li > a`); let This = this; This.emitter = new MyEventEmitter(); This.menuItems.forEach((item) => { item.addEventListener("click", (e) => { item.classList.toggle("selected"); This.emitter.emit("done", item); }); }); }; const myNavMenu = new NavMenu(".menu-wrap"); (function (NavMenu) { const menuItems = document.querySelectorAll(".menu-wrap li > a"); menuItems.forEach((item) => { item.addEventListener("click", (e) => { NavMenu.emitter.on("done", (menuItem) => { const selectedItems = document.querySelectorAll( ".menu-wrap li > a.selected" ); let str = "Selected: "; if (selectedItems.length) { selectedItems.forEach((item, i) => { str += `${item.textContent} `; }); } else { str += `none`; } document.querySelector("#results").innerText = `${str}`; }); }); }); })(myNavMenu);
about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda