@dimentimor

Как обрабатывать события пользовательских объектов?

Здравствуйте!

Как написать что-то вроде этого?

var user = {
  name: 'Jack'
};

user.onEvent('myCustomEvent', function (data) {
  console.log(data);
});

user.trigger('myCustomEvent', 'hello world');


Сейчас я обрабатываю события через window. Обработчик события вызывается в контексте user.
Но хотелось бы обрабатывать кастомные события непосредственно на объекте, а не через другой объект.
Или может быть можно позаимствовать метод addEventListener у window?
  • Вопрос задан
  • 312 просмотров
Решения вопроса 2
lazalu68
@lazalu68
Salmon
Можно, конечно, и самому писать методы, но мне кажется проще пользоваться интерфейсом Emitter:

class Emitter {
  constructor() {
    var delegate = document.createDocumentFragment();
    [
      'addEventListener',
      'dispatchEvent',
      'removeEventListener'
    ].forEach(f => {
		  if (f !== 'dispatchEvent') {
        this[f] = (...xs) => delegate[f](...xs)
      } else {
        this[f] = (eventName, ...xs) => delegate[f](new Event(eventName), ...xs)
      }
    })
  }
}

// sample class to use Emitter
class Example extends Emitter {}

// run it
var e = new Example()
e.addEventListener('something', event => console.log('Something is happened!'))
e.dispatchEvent('something')


То есть конструктор просто редиректит вам методы, которыми вы привыкли работать с любым EventTarget. Это делается с помощью фейкового элемента, в конструкторе он называется delegate. Названия методов конечно можно использовать любые: on, off и т.д.
Ответ написан
SPAHI4
@SPAHI4
реактовцы - это не девы, а прокидыватели пропсов
Воспользуйтесь готовым решением, которое стандарт в nodejs

https://github.com/Olical/EventEmitter
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
crazy_leo
@crazy_leo
Frontend Developer
Minimitter = function Minimitter() {
  this.listeners = {};
};

Minimitter.prototype.on = function(name, callback) {
  this.listeners[name] = this.listeners[name] || [];
  this.listeners[name].push(callback);
};

Minimitter.prototype.off = function(name, callback) {
  this.listeners[name] = this.listeners[name] || [];
  var indexOfCallback = this.listeners[name].indexOf(callback);
  if(~indexOfCallback) {
    this.listeners[name].splice(indexOfCallback, 1);
  }
};

Minimitter.prototype.emit = function(name, data) {
  this.listeners[name].forEach(function(callback) {
    try {
      callback(data);
    } catch(err) {
      console.error('A callback has failed.');
    }
  });
};

var test = Object.create(new Minimitter);

test.on("user", function (name) {
  console.log("Username:", name)
})

test.emit("user", "Bob")
Ответ написан
evgeniy8705
@evgeniy8705
Повелитель вселенной
class EventEmitter {
  constructor() {
    this.listeners = {};
  }

  on(event, cb) {
    this.listeners[event] = this.listeners[event] || [];
    
    this.listeners[event].push(cb);
  }
  
  emit(event) {
    for (let cb of this.listeners[event]) {
      cb();
    }
  }
}

class User extends EventEmitter {
  constructor(name) {
    super();
    
    this.name = name;
  }
}

const user = new User("Alex");

user.on("greeting", () => {
  console.log("Hello " + user.name);
});

user.on("farewell", () => {
  console.log("Bye bye " + user.name);
});

setTimeout(() => {
  user.emit("greeting"); // Hello Alex
}, 3000);

setTimeout(() => {
  user.emit("farewell"); // Bye bye Alex
}, 6000);
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы