2012-01-31 56 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();