使用谷歌关闭创建活动

时间:2012-01-31 22:45:02

标签: javascript google-closure

我想在谷歌闭包(GC)环境中使用事件在我的对象之间进行通信。

假设我有两个类foobar.Bossfoobar.Employee。老板想知道员工什么时候煮咖啡,以及咖啡是否是咖啡因(他本周正在解雇咖啡因)。

GC提供的课程似乎提供了执行此操作的方法,goog.events.Eventgoog.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感到困惑 - 目标调度事件如何?目标不是有事情发生的吗?

This question很有帮助,但我们将非常感谢您提供更直接的答案。

3 个答案:

答案 0 :(得分:10)

看了一会儿之后,我的理解是,EventTarget实际上扮演了一个双重卷,即调度事件的实体和被收听的实体。因此,一个选项是让Employee继承goog.events.EventTarget,但我已经走了另一条路。

首先,我创建了一个新的事件类型,让Boss知道咖啡是否是无咖啡因。

/**
 * @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);
}

先生。 Bossman听了这个。

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 :(得分:1)

我对EventTarget的看法是:

按钮是一个目标,您可以注册该目标,以便在发生任何事件时收到有关其点击事件的通知。因此,点击的“目标”是按钮(您瞄准按钮,然后单击它)。但是当点击按钮时,不是鼠标告诉每个人按钮被点击 - 按钮本身会调度该消息。

触及@ ben-flynn提出的关于为什么有人需要/想要继承EventTarget 的问题:

如果您想收听按键事件,您可能会关心按下了哪个键。您知道键被按下的方式是通过查找KeyDownEventTarget调度的事件对象上的keyCode字段。另一方面,ButtonEventTarget调度一个不同的事件对象,即ClickEvent,其中没有keyCode字段。总而言之,您将子类化为EventTarget的原因是,无论是谁正在侦听将由该目标调度的事件,都知道在触发事件时将调度哪个事件对象。

答案 2 :(得分:0)

这是我怎么做的......

让我们设置咖啡类型。如果我们更进一步,我们可以有一个基础Coffee类,然后用DecafCoffee类子类。但是让我们保持简单。

<强> foobar.Coffee.js

/**
 * @fileoverview Coffee class
 */

goog.provide('foobar.Coffee');

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

我们的Employee类必须实现 goog.events.EventTarget 才能分派事件。你不能忘记用goog.basegoog.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();