使用谷歌关闭创建事件

Creating events with google closure

本文关键字:创建 事件 谷歌      更新时间:2023-09-26

我想在google闭包(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弄糊涂了——目标如何调度事件?难道一个目标不会发生什么事吗?

这个问题很有帮助,但如果能给出更直接的答案,我们将不胜感激。

看了一段时间后,我的理解是,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);
}

Mr。老板听了。

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

请注意,这不会告诉我哪个员工重新装满了咖啡,因为事件目标将是CoffeeEventTarget的实例。如果您希望所有Employee都在其中,我想您可以将其添加为成员字段。如果您可以从goog.events.EventTarget继承到Employee,那么您可以免费获得Employee作为目标。

我对EventTarget的看法是:

按钮是一个目标,您可以注册该按钮,以便在发生点击事件时收到通知。因此,点击的"目标"是按钮(你瞄准按钮,然后点击它)。但当按钮被点击时,并不是鼠标告诉每个人按钮被点击了,而是按钮本身发出消息。

为了触及@ben flynn提出的关于的问题,为什么有人需要/想要将EventTarget子类化

如果您想监听按键按下事件,您可能会关心按下了什么键。您可以通过查找KeyDownEventTarget调度的事件对象上的keyCode字段来了解按下了什么键。另一方面,ButtonEventTarget调度一个不同的事件对象,即ClickEvent,该对象中没有keyCode字段。因此,总的来说,您之所以将EventTarget子类化,是因为无论谁在侦听将由该目标调度的事件,都知道当事件被触发时将调度什么事件对象。

以下是我的操作方法…

让我们设置一个咖啡类型。如果我们更进一步,我们可以有一个基础咖啡课程,然后用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.Employe.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
    });
};

boss类不需要做任何特殊的事情,因为它不会调度事件。它只需要一个我们可以调用的#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();