2012-01-31 34 views
9

Tôi muốn sử dụng các sự kiện để giao tiếp giữa các đối tượng của mình trong môi trường đóng cửa google (GC).Tạo sự kiện với google closure

Giả sử tôi có hai lớp foobar.Bossfoobar.Employee. Ông chủ muốn biết khi nào nhân viên đã pha cà phê, và liệu cà phê đó có phải là decaf (anh ta đang dùng cà phê trong tuần này).

GC đã cung cấp các lớp học có vẻ như cung cấp phương tiện để thực hiện việc này, goog.events.Eventgoog.events.EventTarget.

Mà không biết tốt hơn, tôi nghĩ rằng nó sẽ làm việc như thế này:

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); 
    ... 
} 

Đây có phải là một mô hình có đúng không? Tôi bị nhầm lẫn bởi lớp học goog.events.EventTarget - sự kiện gửi đi mục tiêu như thế nào? Không phải là một mục tiêu có những điều xảy ra với nó?

This question là hữu ích, nhưng câu trả lời trực tiếp hơn sẽ được đánh giá cao.

+0

http://code.google.com/p/closure-library/source/browse/trunk/closure/goog/fx/fx.js?r=2 # 582 Việc triển khai ví dụ - kế thừa từ goog.events.EventTarget có vẻ kỳ lạ (có cần thiết là Nhân viên mở rộng EventTarget không?) –

Trả lời

9

Sau khi xem xét điều này một chút, sự hiểu biết của tôi bây giờ là EventTarget thực tế phát một cuộn kép là thực thể gửi các sự kiện và thực thể được nghe. Vì vậy, một tùy chọn sẽ là có Employee kế thừa goog.events.EventTarget nhưng tôi đã đi một tuyến đường khác.

Trước tiên, tôi đã tạo một loại sự kiện mới sẽ cho phép Boss biết nếu cà phê đã bị hỏng.

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

Tiếp theo, tôi đã tạo loại trình xử lý sự kiện để gửi các sự kiện này.

/** 
* @constructor 
* @extends {goog.events.EventTarget} 
*/ 
foobar.CoffeeEventTarget = function() 
{ 
    goog.events.EventTarget.call(this); 
}; 
goog.inherits(foobar.CoffeeEventTarget, goog.events.EventTarget); 

Tôi đã thêm một đối tượng thuộc loại này vào Employee.

foobar.Employee = function() 
{ 
    ... 
    this.coffeeEvents = new foobar.CoffeeEventTarget(); 
    ... 
} 

Khi người lao động Refills cà phê:

foobar.Employee.prototype.makeCoffee = function(isDecaf) 
{   
    this.coffeeMaker.putCoffeeInMachine(isDecaf); 
    this.coffeeMaker.start(); 
    var event = new foobar.CoffeeEvent(isDecaf); 
    this.coffeeEvents.dispatchEvent(event); 
} 

Ông Bossman nghe cho việc này.

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

Lưu ý rằng điều này sẽ không cho tôi biết nhân viên nạp lại cà phê, bởi vì mục tiêu sự kiện sẽ một thể hiện của CoffeeEventTarget. Nếu bạn muốn tất cả các Employee trong đó tôi giả sử bạn có thể thêm nó như là một lĩnh vực thành viên. Nếu bạn đồng ý với kế thừa Employee từ goog.events.EventTarget thì bạn sẽ nhận được miễn phí Employee làm mục tiêu.

+0

foobar.CoffeeEvent có lẽ nên chấp nhận một loại, thay vì bị mã hóa cứng. Đây sẽ là một sử dụng tốt cho một enum. –

+0

Vẫn đang xem xét điều này. Có lẽ không có nhu cầu thực sự nào trong trường hợp của tôi để phân lớp EventTarget. –

1

Con đường tôi nghĩ về EventTarget là thế này:

Một nút là một mục tiêu mà bạn có thể đăng ký để được thông báo về sự kiện click của mình bất cứ khi nào một diễn ra. Vì vậy, "mục tiêu" của một nhấp chuột là nút (bạn nhắm vào nút, sau đó nhấp vào nó). Nhưng khi nút được nhấp vào, nó không phải là con chuột cho mọi người biết rằng nút đã được nhấp - nút tự gửi đi thông báo đó.

Để chạm về vấn đề nuôi dưỡng bởi @ ben-Flynn về tại sao một người nào đó cần/muốn phân lớp EventTarget:

Nếu bạn muốn nghe cho phím xuống sự kiện, bạn có thể quan tâm đến những gì đã được nhấn. Cách bạn biết khóa được nhấn là gì bằng cách tra cứu trường mã phím trên đối tượng sự kiện được gửi bởi KeyDownEventTarget. Mặt khác, một ButtonEventTarget gửi một đối tượng sự kiện khác nhau, cụ thể là một ClickEvent, mà không có một trường keyCode trong đó. Vì vậy, để tóm tắt, lý do bạn muốn phân lớp EventTarget là để mọi người lắng nghe các sự kiện sẽ được gửi đi bởi mục tiêu đó biết đối tượng sự kiện nào sẽ được gửi đi khi sự kiện được kích hoạt.

0

Đây là cách tôi sẽ thực hiện ...

Hãy thiết lập loại cà phê. Nếu chúng tôi thực hiện điều này hơn nữa, chúng tôi có thể có một lớp học cơ bản về Cà phê và sau đó học lớp đó với lớp DecafCoffee. Nhưng hãy để mọi thứ đơn giản.

foobar.Coffee.js

/** 
* @fileoverview Coffee class 
*/ 

goog.provide('foobar.Coffee'); 

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

class Employee của chúng ta phải thực hiện goog.events.EventTarget để có thể cử các sự kiện. Bạn không được quên gọi hàm tạo của cha mẹ với goog.base hoặc goog.events.EventTarget.call hoặc vì điều này sẽ thiết lập các biến nội bộ mà lớp cần.

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 
    }); 
}; 

Lớp ông chủ không cần phải làm bất cứ điều gì đặc biệt vì nó sẽ không được cử các sự kiện. Nó chỉ cần một phương pháp #drinkCoffee() chúng ta có thể gọi.

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){ 
    //.... 
}; 

Đây là mã Javascript chính mà bạn sẽ được chạy, bạn có thể đặt bất cứ nơi nào mà bạn thích, ví dụ nội tuyến trong trình duyệt hoặc trong tập lệnh của chính nó.

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(); 
Các vấn đề liên quan