es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Burbujeo de eventos en objeto JavaScript puro.

Quiero implementar un sistema de eventos en un objeto JS puro que sea similar a los eventos del DOM, que se puedan despachar y propagarse desde un objeto hijo hacia el objeto padre.
¿Puedo usar interfaces existentes como EventTarget o Event para hacer esto? ¿Cuál es la forma correcta de lograrlo?

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Preview Pro</title>
</head>

<body>
  <div id="app"></div>
  <script>
    class body extends EventTarget {
      constructor(name, parent) {
        super();
        this.name = name;
        this.type = 'body';
        this.parentNode = parent;
      }
    };

    class hand extends body {
      constructor(name, parent) {
        super(name, parent);
        this.type = 'hand';
      }
    }

    class finger extends body {
      constructor(name, parent) {
        super(name, parent);
        this.type = 'finger';
      }
    }

    var human = new body('stanley');
    var left_hand = new hand('left_hand', human);
    var thumb = new finger('thumb', left_hand);
    left_hand.addEventListener('touch', function (e) {
      // bubbling
      console.log(e)
    });

    thumb.addEventListener('touch', function (e) {
      // target
      console.log(e)
    });

    thumb.dispatchEvent(new Event('touch', {bubbles: true}));
  </script>
</body>

</html>

Después de buscar un poco, encontré esta respuesta. Aún utiliza el árbol DOM para asegurarse de que el evento se propague desde el hijo hacia el padre. ¿Se puede hacer esto sin utilizar el árbol DOM?

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Sí, es posible implementar un sistema de eventos en un objeto JS puro sin usar el árbol DOM. Una forma de lograr esto es creando un sistema de eventos personalizado que imite el comportamiento de los eventos del DOM. Puedes crear una clase para el objeto evento que incluya propiedades como type, target, currentTarget, bubbles, etc. Luego, puedes crear un método en el objeto que te permita despachar eventos y hacer que se propaguen a lo largo de la jerarquía del objeto. Aquí tienes un ejemplo de cómo se podría implementar:

    class MyObject {
      constructor() {
        this._listeners = {};
        this._parent = null;
      }
    
      addEventListener(type, listener) {
        if (typeof this._listeners[type] === 'undefined') {
          this._listeners[type] = [];
        }
    
        this._listeners[type].push(listener);
      }
    
      removeEventListener(type, listener) {
        if (this._listeners[type] instanceof Array) {
          const listeners = this._listeners[type];
          const index = listeners.indexOf(listener);
    
          if (index !== -1) {
            listeners.splice(index, 1);
          }
        }
      }
    
      dispatchEvent(event) {
        if (typeof this._listeners[event.type] === 'undefined') {
          return;
        }
    
        // Establecer algunas propiedades básicas del objeto evento
        event.target = this;
        event.currentTarget = this;
    
        // Propagar el evento por la jerarquía del objeto
        let currentObject = this;
        const ancestors = [];
    
        while (currentObject) {
          ancestors.push(currentObject);
          currentObject = currentObject._parent;
        }
    
        for (let i = ancestors.length - 1; i >= 0; i--) {
          const listeners = ancestors[i]._listeners[event.type];
    
          if (listeners) {
            for (let j = 0; j < listeners.length; j++) {
              listeners[j].call(this, event);
            }
          }
    
          if (event.bubbles === false) {
            break;
          }
        }
      }
    
      set parent(parentObject) {
        this._parent = parentObject;
      }
    
      get parent() {
        return this._parent;
      }
    }
    

    Esta clase MyObject incluye métodos para agregar y eliminar oyentes de eventos, despachar eventos y establecer el padre del objeto. También incluye una propiedad llamada _listeners que es un objeto que contiene matrices de oyentes de eventos para cada tipo de evento.

    Para crear una jerarquía de objetos que pueda propagar eventos desde objetos hijos hasta objetos padres, simplemente debes establecer la propiedad parent de cada objeto hijo con su objeto padre. Aquí tienes un ejemplo:

    const obj1 = new MyObject();
    const obj2 = new MyObject();
    const obj3 = new MyObject();
    
    obj2.parent = obj1;
    obj3.parent = obj2;
    
    obj1.addEventListener('myevent', function(event) {
      console.log('Evento provocado en obj1');
    });
    
    obj2.addEventListener('myevent', function(event) {
      console.log('Evento provocado en obj2');
    });
    
    obj3.addEventListener('myevent', function(event) {
      console.log('Evento provocado en obj3');
    });
    
    // Esto provocará el evento en obj3, que se propagará a obj2 y luego a obj1
    obj3.dispatchEvent(new CustomEvent('myevent', { bubbles: true }));
    

    En este ejemplo, creamos tres instancias de MyObject y establecemos sus propiedades de padre para crear una jerarquía. Luego, agregamos oyentes de eventos a cada objeto para el evento myevent. Finalmente, despachamos el evento en el objeto hijo (obj3) y se propaga por la jerarquía del objeto, desencadenando los oyentes de eventos en cada objeto padre a su vez.

Comments are closed.