2012-01-31 59 views
9

我想使用事件在Google关闭(GC)环境中的对象之间进行通信。使用Google关闭创建事件

假设我有两个类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很有帮助,但更直接的答案将不胜感激。

+0

http://code.google.com/p/closure-library/source/browse/trunk/closure/goog/fx/fx.js?r=2 #582是一个示例实现 - 从goog.events.EventTarget继承似乎很奇怪(Employee是否完全需要扩展EventTarget?) – 2012-01-31 23:40:13

回答

9

看了这一段时间后,我的理解是现在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在那里,我想你可以添加它作为一个成员字段。如果您还可以从goog.events.EventTarget继承Employee,那么免费获得Employee作为目标。

+0

foobar.CoffeeEvent应该可能接受一个类型,而不是硬编码。这将是一个很好的使用枚举。 – 2012-02-01 21:08:32

+0

仍在看这个。在我的情况下,可能没有真正的需要子类化EventTarget。 – 2012-02-03 06:20:12

1

我认为事件目标的方法是这样的:

一个按钮是一个目标,这时候一个发生,你可以注册到被通知其click事件。因此,点击的“目标”是按钮(你瞄准按钮,然后点击它)。但是,当按钮被点击时,不是鼠标告诉大家按钮被点击 - 按钮本身分派该消息。

触及通过@本 - 弗林约为什么会有人需要/带出来的问题,要继承事件目标

如果你想监听键不放事件,你可能关心什么键被按下。您知道按键的方式是查看由KeyDownEventTarget调度的事件对象上的keyCode字段。另一方面,ButtonEventTarget调度一个不同的事件对象,即一个ClickEvent,它没有keyCode字段。因此,总而言之,您将子类EventTarget的原因是,无论谁在监听由该目标分派的事件,都知道事件触发时将分派哪些事件对象。

0

下面是我该怎么做的...

让我们设置一个咖啡类型。如果我们进一步考虑这个问题,我们可以有一个基本的Coffee类,然后用DecafCoffee类对它进行分类。但让我们保持简单。

foobar.Coffee.js

/** 
* @fileoverview Coffee class 
*/ 

goog.provide('foobar.Coffee'); 

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

我们的员工类必须实现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();