Создание событий с закрытием Google - PullRequest
9 голосов
/ 01 февраля 2012

Я хотел бы использовать события для связи между моими объектами в среде Google Closure (GC).

Предположим, у меня есть два класса foobar.Boss и foobar.Employee. Босс хочет знать, когда Сотрудник приготовил кофе, и является ли этот кофе без кофеина (он отказывается от кофеина на этой неделе).

GC сделал доступными классы, которые, кажется, предоставляют средства для этого, goog.events.Event и goog.events.EventTarget.

Не зная лучше, я бы подумал, что это будет работать так:

foobar.Employee.prototype.makeCoffee = function(isDecaf)
{        
    this.coffeeMaker.putCoffeeInMachine(isDecaf);
    this.coffeeMaker.start();
    var event = new goog.event.Event('COFFEE_ON', { isDecaf: isDecaf });
    goog.events.dispatchEvent(event);
}

foobar.Boss.prototype.addEmployee = function(employee)
{
    ...
    goog.events.listen(employee, 'COFFEE_ON', function(e)
    {
        if (e.target.isDecaf)
        {
            this.refillMug();
        }
    }, false, this);
    ...
}

Это правильный шаблон? Меня смущает класс goog.events.EventTarget - как целевые события отправляются? Разве у цели ничего не происходит с ней?

Этот вопрос полезен, но был бы признателен за более прямой ответ.

Ответы [ 3 ]

10 голосов
/ 01 февраля 2012

Посмотрев на это некоторое время, я теперь понимаю, что EventTarget фактически играет двойную роль: сущность, которая отправляет события, и сущность, которую слушают.Поэтому одним из вариантов было бы иметь Employee наследовать goog.events.EventTarget, но я пошел другим путем.

Сначала я создал новый тип события, который сообщал бы Боссу, если кофе был без кофеина.

/**
 * @constructor
 * @extends {goog.events.Event}
 */
foobar.CoffeeEvent = function(isDecaf)
{
  goog.events.Event.call(this, 'COFFEE_ON');
  this.isDecaf = isDecaf;
};
goog.inherits(foobar.CoffeeEvent, goog.events.Event);

Далее я создал тип прослушивателя событий для отправки этих событий.

/**
 * @constructor
 * @extends {goog.events.EventTarget} 
 */
foobar.CoffeeEventTarget = function()
{
  goog.events.EventTarget.call(this);
};
goog.inherits(foobar.CoffeeEventTarget, goog.events.EventTarget);

Я добавил объект этого типа в мой Employee.

foobar.Employee = function()
{
  ...
  this.coffeeEvents = new foobar.CoffeeEventTarget();
  ...
}

Когдаработник заправляет кофе:

foobar.Employee.prototype.makeCoffee = function(isDecaf)
{        
    this.coffeeMaker.putCoffeeInMachine(isDecaf);
    this.coffeeMaker.start();
    var event = new foobar.CoffeeEvent(isDecaf);
    this.coffeeEvents.dispatchEvent(event);
}

г-н.Боссман прислушивается к этому.

foobar.Boss.prototype.addEmployee = function(employee)
{
    ...
    goog.events.listen(employee.coffeeEvents, 'COFFEE_ON', function(e)
    {
        if (e.isDecaf)
        {
            this.refillMug();
        }
    }, false, this);
    ...
}

Обратите внимание, что это не скажет мне , какой сотрудник наполнил кофе, потому что целью события будет экземпляр CoffeeEventTarget.Если бы вы хотели, чтобы все Employee было там, я полагаю, вы можете добавить его в качестве поля участника.Если у вас все в порядке с наследованием Employee от goog.events.EventTarget, тогда вы получите Employee бесплатно в качестве цели.

1 голос
/ 19 сентября 2013

Я думаю о EventTarget так:

A button - это цель, которую вы можете зарегистрировать, чтобы получать уведомления о событии щелчка всякий раз, когда это происходит.Таким образом, «цель» щелчка - кнопка (вы нацеливаетесь на кнопку, затем нажимаете на нее).Но когда кнопка нажата, это не мышка, которая сообщает всем, что кнопка нажата - сама кнопка отправляет это сообщение.

Чтобы затронуть вопрос, заданный @ ben-flynn о , почемукто-то должен / хочет создать подкласс EventTarget :

Если вы хотите прослушивать события key down , вам, вероятно, важно, какая клавиша была нажата.Чтобы узнать, какая клавиша была нажата, нужно посмотреть в поле keyCode объекта event , отправляемого KeyDownEventTarget.С другой стороны, ButtonEventTarget отправляет другой объект события, а именно ClickEvent, в котором нет поля keyCode.Итак, подведем итог: причина, по которой вы бы создали подкласс EventTarget, заключается в том, чтобы тот, кто прослушивает события, которые будут отправлены этой целью, знал, какой объект события будет отправлен при его запуске.

0 голосов
/ 29 мая 2015

Вот как бы я это сделал ...

Давайте настроим тип кофе.Если бы мы пошли дальше, у нас мог бы быть базовый класс Coffee, а затем подкласс - классом DecafCoffee.Но давайте все упростим.

foobar.Coffee.js

/**
 * @fileoverview Coffee class
 */

goog.provide('foobar.Coffee');

/**
 * @constructor
 */
foobar.Coffee = function(){
   //...
};

Наш класс Employee должен реализовывать goog.events.EventTarget , чтобы бытьвозможность отправлять события.Вы не должны забывать вызывать родительский конструктор с помощью goog.base или goog.events.EventTarget.call, так как это установит внутренние переменные, необходимые классу.

foobar.Employee.js

/**
 * @fileoverview Implements the Employee class
 */

goog.provide('foobar.Employee');
goog.require('goog.events.EventTarget');
goog.require('foobar.Coffee');

/**
 * @constructor
 */
foobar.Employee = function(){
    // Calls the parent class (goog.events.EventTarget)
    goog.base(this);
};
goog.inherits(foobar.Employee, goog.events.EventTarget);

/**
 * Make a coffee
 */
foobar.Employee.prototype.makeCoffee = function(){
    // Determine what coffee type to make ...
    // Create the coffee
    var coffee = new foobar.Coffee();
    this.dispatchEvent({
        type: "decaf_coffee",
        target: coffee
    });
};

Класс босса не должен делать ничего особенного, поскольку он не будет отправлять события.Ему просто нужен метод #drinkCoffee(), который мы можем вызвать.

foobar.Boss.js

/**
 * @fileoverview Implements the Boss class
 */

goog.provide('foobar.Boss');

/**
 * @constructor
 */
foobar.Boss = function(){
   //...
};

/**
 * Make this boss drink coffee
 * @param {foobar.Coffee} coffee The coffee to drink
 */
foobar.Boss.prototype.drinkCoffee = function(coffee){
    //....
};

Это основной код JavaScript, который вы будете запускатьВы можете поместить куда угодно, например, в браузер или в собственный скрипт.

main.js

goog.require('foobar.Boss');
goog.require('foobar.Employee');
goog.require('goog.events');

// Jane is the boss of Sam, but we will use lower case as I typically 
// only capitalise the first letter to indicate a constructor.
var jane = new Boss();
var sam = new Employee();

// Set up event listening
goog.events.listen(sam, "decaf_coffee", function(e){
    var coffee = e.target;
    // We've got the decaf coffee Sam made, now Jane can enjoy drinking it
    jane.drinkCoffee(coffee);
}, false, this);

// Tell Sam to make a coffee
sam.makeCoffee();
...