2017-06-06 50 views
0

我在打字稿中製作了此按鈕類。我已經給它一個「默認」函數來處理點擊事件。但是,如果我想要傳遞一個函數作爲參數並在點擊時調用傳遞的函數呢?重寫打字稿類中的默認功能

下面的代碼:

abstract class BaseButton { 

    element:HTMLElement; 
    label:string; 

    constructor(element:HTMLElement, label:string) { 
    console.log(this); 
    this.element = element; 
    this.label = label; 
    this.init(); 
    } 

    init():void { 
    this.setText(this.label); 
    this.addListeners(); 
    } 

    setText(label:string):void { 
    this.element.innerHTML = label; 
    } 

    kill():void { 
    this.removeListeners(); 
    } 

    addListeners():void { 
    this.element.addEventListener("mouseover", this.onMouseOver); 
    this.element.addEventListener("click", this.onClick); 
    this.element.addEventListener("mouseout", this.onMouseOut); 
    this.element.addEventListener('touchstart', this.onTouchStart); 
    this.element.addEventListener('touchmove', this.onTouchMove); 
    this.element.addEventListener('touchcancel', this.onTouchCancel); 
    this.element.addEventListener('touchend', this.onTouchEnd); 
    } 

    removeListeners():void { 
    this.element.removeEventListener("mouseover", this.onMouseOver); 
    this.element.removeEventListener("click", this.onClick); 
    this.element.removeEventListener("mouseout", this.onMouseOut); 
    this.element.removeEventListener('touchstart', this.onTouchStart); 
    this.element.removeEventListener('touchmove', this.onTouchMove); 
    this.element.removeEventListener('touchcancel', this.onTouchCancel); 
    this.element.removeEventListener('touchend', this.onTouchEnd); 
    } 

    onTouchStart():void { 

    } 

    onTouchMove():void { 

    } 

    onTouchCancel():void { 

    } 

    onTouchEnd():void { 

    } 

    onMouseOver():void { 
    console.log('mouse over'); 
    } 

    onMouseOut():void { 
    console.log('mouse out'); 
    } 

    abstract onClick(event:Event):void 
} 

class Button extends BaseButton { 

    element:HTMLElement; 
    label:string; 
    callback:any; 

    constructor(element:HTMLElement, label:string, callback?:() => void) { 
    super(element,label); 
    this.element = element; 
    this.label = label; 
    this.callback = callback; 
    } 

    onClick(event:Event):void { 
    if (this.callback) { 
     console.log('ddd'); 
     this.callback(); 
    } 
    } 
} 





const el = document.getElementById('btn'); 
const button = new Button(el,'Click'); 

const ell = document.getElementById('btnn'); 
const buttonn = new Button(ell,'Click'); 

const elll = document.getElementById('btnnn'); 
const buttonnn = new Button(elll,'Click',() => { 
    alert('fff'); 
}); 

回答

0

你失去的子類的onClick函數內的this時參考下面的事件處理在基類中運行:

this.element.addEventListener("click", this.onClick) 

通常情況下,這可能通過使用箭頭功能解決:

class Button extends BaseButton { 
    constructor(element: HTMLElement, label: string, private callback?:() => void) { 
    super(element, label); 
    } 

    onClick = (event: Event) => { 
    if (this.callback) { 
     this.callback(); 
    } 
    } 
} 

但是,在這種特殊情況下,如果你嘗試在子類中定義它,你會得到以下錯誤:

Class 'BaseButton' defines instance member function 'onClick', but extended class 'Button' defines it as instance member property.

如果你嘗試定義在子類的構造函數onClick箭頭功能:

class Button extends BaseButton { 
    constructor(element: HTMLElement, label: string, private callback?:() => void) { 
    super(element, label); 

    this.onClick =() => { 
     // ... 
    } 
    } 
} 

您會收到以下錯誤:

Non-abstract class 'Button' does not implement inherited abstract member 'onClick' from class 'BaseButton'

如果你嘗試創建一個存根方法只是爲了讓錯誤消失,並創建真正的一種方法,在構造一個箭頭功能:

class Button extends BaseButton { 
    constructor(element: HTMLElement, label: string, private callback?:() => void) { 
    super(element, label); 

    this.onClick =() => { 
     // ... 
    } 
    } 

    onClick(event: Event) { } 
} 

它不會工作,因爲,因爲該代碼,子類的構造函數之前運行的基類會傳遞錯誤的onClick功能參考addEventListener

以下是一種解決方法。在基類中綁定this,在那裏創建一個單獨的函數,調用this.onClick(),並保留對該新函數的引用,以便您可以註銷它。

abstract class BaseButton { 
    private onClickBound; 

    constructor(protected element: HTMLElement, protected label: string) { 
    this.init(); 
    } 

    init(): void { 
    this.addListeners(); 
    } 

    kill(): void { 
    this.removeListeners(); 
    } 

    addListeners(): void { 
    this.onClickBound = (e: Event) => this.onClick(e); 

    // Or you can do this: 
    // this.onClickBound = this.onClick.bind(this) 

    this.element.addEventListener("click", this.onClickBound); 
    } 

    removeListeners(): void { 
    this.element.removeEventListener("click", this.onClickBound); 
    } 

    abstract onClick(event: Event); 
} 

class Button extends BaseButton { 
    constructor(element: HTMLElement, label: string, private callback?:() => void) { 
    super(element, label); 
    } 

    onClick(event: Event) { 
    if (this.callback) { 
     this.callback(); 
    } 
    } 
} 

我會試着想出一個更乾淨的解決方案,因爲我對這個不是很滿意。

+0

嗨,謝謝!也許我還不夠清楚。我想要做的就是重載點擊按鈕,如果點擊處理程序作爲參數傳遞。 – user2952238

+0

我相信我的代碼可以滿足你的要求。讓我知道你是否需要修改。 –

+0

它給了我以下錯誤:TypeError:this。 clickHandler不是一個函數。 – user2952238

0

如果你做了這樣的事情(加入其他代碼)會怎麼樣?

class Button { 
    clickListener; // with any types 

    constructor(clickListener = defaultClickListener) { 
     this.clickListener = clickListener; 
     this.clickListener(); 
    } 
} 

function defaultClickListener():void { 
    console.log(0); 
} 

new Button(() => console.log(1));