TypeScript는 클래스에 대한 이벤트를 지원합니까?
TypeScript에서 클래스 또는 인터페이스에 사용자 지정 이벤트를 정의 할 수 있는지 궁금합니다.
이것은 어떤 모습일까요?
이 단순화 된 이벤트를 속성으로 사용하는 것은 어떻습니까? 소유 클래스의 강력한 타이핑 및 상속 요구 사항 없음 :
interface ILiteEvent<T> {
on(handler: { (data?: T): void }) : void;
off(handler: { (data?: T): void }) : void;
}
class LiteEvent<T> implements ILiteEvent<T> {
private handlers: { (data?: T): void; }[] = [];
public on(handler: { (data?: T): void }) : void {
this.handlers.push(handler);
}
public off(handler: { (data?: T): void }) : void {
this.handlers = this.handlers.filter(h => h !== handler);
}
public trigger(data?: T) {
this.handlers.slice(0).forEach(h => h(data));
}
public expose() : ILiteEvent<T> {
return this;
}
}
이렇게 사용 :
class Security{
private readonly onLogin = new LiteEvent<string>();
private readonly onLogout = new LiteEvent<void>();
public get LoggedIn() { return this.onLogin.expose(); }
public get LoggedOut() { return this.onLogout.expose(); }
// ... onLogin.trigger('bob');
}
function Init() {
var security = new Security();
var loggedOut = () => { /* ... */ }
security.LoggedIn.on((username?) => { /* ... */ });
security.LoggedOut.on(loggedOut);
// ...
security.LoggedOut.off(loggedOut);
}
개량?
타이프 라이터에 대한 강력한 형식의 이벤트 프로젝트 (버전 0.3 :) 구현 이벤트의 3 종류 IEvent<TSender, TArgs>
, ISimpleEvent<TArgs>
및 ISignal
. 이렇게하면 프로젝트에 적합한 종류의 이벤트를 더 쉽게 사용할 수 있습니다. 또한 좋은 정보 숨김이 수행해야하는 것처럼 이벤트에서 디스패치 메서드를 숨 깁니다.
이벤트 유형 / 인터페이스 - 이벤트 의 정의 :
interface IEventHandler<TSender, TArgs> {
(sender: TSender, args: TArgs): void
}
interface ISimpleEventHandler<TArgs> {
(args: TArgs): void
}
interface ISignalHandler {
(): void;
}
예 -이 예는 똑딱 거리는 시계를 사용하여 세 가지 유형의 이벤트를 구현하는 방법을 보여줍니다.
class Clock {
//implement events as private dispatchers:
private _onTick = new SignalDispatcher();
private _onSequenceTick = new SimpleEventDispatcher<number>();
private _onClockTick = new EventDispatcher<Clock, number>();
private _ticks: number = 0;
constructor(public name: string, timeout: number) {
window.setInterval( () => {
this.Tick();
}, timeout);
}
private Tick(): void {
this._ticks += 1;
//trigger event by calling the dispatch method and provide data
this._onTick.dispatch();
this._onSequenceTick.dispatch(this._ticks);
this._onClockTick.dispatch(this, this._ticks);
}
//expose the events through the interfaces - use the asEvent
//method to prevent exposure of the dispatch method:
public get onTick(): ISignal {
return this._onTick.asEvent();
}
public get onSequenceTick() : ISimpleEvent<number>{
return this._onSequenceTick.asEvent();
}
public get onClockTick(): IEvent<Clock, number> {
return this._onClockTick.asEvent();
}
}
사용법 -다음과 같이 사용할 수 있습니다.
let clock = new Clock('Smu', 1000);
//log the ticks to the console
clock.onTick.subscribe(()=> console.log('Tick!'));
//log the sequence parameter to the console
clock.onSequenceTick.subscribe((s) => console.log(`Sequence: ${s}`));
//log the name of the clock and the tick argument to the console
clock.onClockTick.subscribe((c, n) => console.log(`${c.name} ticked ${n} times.`))
자세한 내용은 여기에서 확인하세요 : 이벤트, 디스패처 및 목록 (시스템에 대한 일반적인 설명)
튜토리얼
주제에 대한 튜토리얼을 몇 개 작성했습니다.
- TypeScript의 강력한 형식의 이벤트 핸들러 (1 부)
- 인터페이스가있는 TypeScript에서 강력한 형식의 이벤트 사용 (2 부)
- 이벤트 목록을 사용하는 TypeScript의 강력한 형식 이벤트 (3 부)
- 클래스에 명명 된 이벤트 추가 (4 부)
- 0.2.0 단순 이벤트 지원
- 0.3.0 신호 지원
클래스 인스턴스가 DOM 요소처럼 addEventListener () 및 dispatchEvent ()를 구현할 수 있는지 묻고 있다고 생각합니다. 클래스가 DOM 노드가 아니면 자체 이벤트 버스를 작성해야합니다. 이벤트를 게시 할 수있는 클래스에 대한 인터페이스를 정의한 다음 클래스에서 인터페이스를 구현합니다. 다음은 순진한 예입니다.
interface IEventDispatcher{
// maintain a list of listeners
addEventListener(theEvent:string, theHandler:any);
// remove a listener
removeEventListener(theEvent:string, theHandler:any);
// remove all listeners
removeAllListeners(theEvent:string);
// dispatch event to all listeners
dispatchAll(theEvent:string);
// send event to a handler
dispatchEvent(theEvent:string, theHandler:any);
}
class EventDispatcher implement IEventDispatcher {
private _eventHandlers = {};
// maintain a list of listeners
public addEventListener(theEvent:string, theHandler:any) {
this._eventHandlers[theEvent] = this._eventHandlers[theEvent] || [];
this._eventHandlers[theEvent].push(theHandler);
}
// remove a listener
removeEventListener(theEvent:string, theHandler:any) {
// TODO
}
// remove all listeners
removeAllListeners(theEvent:string) {
// TODO
}
// dispatch event to all listeners
dispatchAll(theEvent:string) {
var theHandlers = this._eventHandlers[theEvent];
if(theHandlers) {
for(var i = 0; i < theHandlers.length; i += 1) {
dispatchEvent(theEvent, theHandlers[i]);
}
}
}
// send event to a handler
dispatchEvent(theEvent:string, theHandler:any) {
theHandler(theEvent);
}
}
TypeScript에서 사용자 정의 이벤트를 사용할 수 있습니다. 정확히 무엇을 하려는지 잘 모르겠지만 여기에 예가 있습니다.
module Example {
export class ClassWithEvents {
public div: HTMLElement;
constructor (id: string) {
this.div = document.getElementById(id);
// Create the event
var evt = document.createEvent('Event');
evt.initEvent('customevent', true, true);
// Create a listener for the event
var listener = function (e: Event) {
var element = <HTMLElement> e.target;
element.innerHTML = 'hello';
}
// Attach the listener to the event
this.div.addEventListener('customevent', listener);
// Trigger the event
this.div.dispatchEvent(evt);
}
}
}
좀 더 구체적인 작업을 원하시면 알려주세요.
이 솔루션을 사용하면 모든 매개 변수를 객체에 래핑 할 필요없이 함수 호출에서 매개 변수를 직접 작성할 수 있습니다.
interface ISubscription {
(...args: any[]): void;
}
class PubSub<T extends ISubscription> {
protected _subscribed : ISubscriptionItem[] = [];
protected findSubscription(event : T) : ISubscriptionItem {
this._subscribed.forEach( (item : ISubscriptionItem) =>{
if (item.func==event)
return item;
} );
return null;
}
public sub(applyObject : any,event : T) {
var newItem = this.findSubscription(event);
if (!newItem) {
newItem = {object : applyObject, func : event };
this._subscribed.push(newItem);
this.doChangedEvent();
}
}
public unsub(event : T) {
for ( var i=this._subscribed.length-1 ; i>=0; i--) {
if (this._subscribed[i].func==event)
this._subscribed.splice(i,1);
}
this.doChangedEvent();
}
protected doPub(...args: any[]) {
this._subscribed.forEach((item : ISubscriptionItem)=> {
item.func.apply(item.object, args);
})
}
public get pub() : T {
var pubsub=this;
var func= (...args: any[]) => {
pubsub.doPub(args);
}
return <T>func;
}
public get pubAsync() : T {
var pubsub=this;
var func = (...args: any[]) => {
setTimeout( () => {
pubsub.doPub(args);
});
}
return <T>func;
}
public get count() : number {
return this._subscribed.length
}
}
용법:
interface ITestEvent {
(test : string): void;
}
var onTestEvent = new PubSub<ITestEvent>();
//subscribe to the event
onTestEvent.sub(monitor,(test : string) => {alert("called:"+test)});
//call the event
onTestEvent.pub("test1");
표준 이미 터 패턴을 사용하여 인텔리 센스 유형 검사를 얻으려면 이제 다음을 수행 할 수 있습니다.
type DataEventType = "data";
type ErrorEventType = "error";
declare interface IDataStore<TResponse> extends Emitter {
on(name: DataEventType, handler : (data: TResponse) => void);
on(name: ErrorEventType, handler: (error: any) => void);
}
참고URL : https://stackoverflow.com/questions/12881212/does-typescript-support-events-on-classes
'programing' 카테고리의 다른 글
boost :: unique_lock 대 boost :: lock_guard (0) | 2020.12.11 |
---|---|
jQuery / Twitter Bootstrap 데이터 로딩 텍스트 버튼 (지연 포함) (0) | 2020.12.11 |
JavaScript : 1 분마다 실행할 코드 가져 오기 (0) | 2020.12.11 |
Sublime Text 2 파일 사이드 바의 글꼴 크기를 변경하는 방법은 무엇입니까? (0) | 2020.12.11 |
Linux free는 높은 메모리 사용량을 표시하지만 top은 그렇지 않습니다. (0) | 2020.12.11 |