我想在谷歌闭包(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
感到困惑 - 目标调度事件如何?目标不是有事情发生的吗?
This question很有帮助,但我们将非常感谢您提供更直接的答案。
答案 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.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();