現在1つのvueファイルにまとめていた機能を、Elementごとに役割分担させるためファイルを分けて再利用しやすくしているのですが、TypeScriptのクラス内でaddEventListenerに関数を渡すと、thisがメンバではなく、要素自体を指します。
```js
class Textarea {
private _textarea: HTMLTextAreaElement;
constuctor(textarea: HTMLElement) {
super();
this._textarea = textarea as HTMLTextAreaElement;
this._textarea.addEventListener('input', this._onInput);
}
private _onInput(ev: Event):void {
console.log(this._textarea.value);
}
}
```
テキストエリアに入力するたびコンソールでテキストエリアの中身を確認するメソッドを用意しましたが、valueがない(実際はthisに_textareaがない)とエラーが返ってきます。
この場合の`this`はクラスを指しているのではなく、`HTMLTextAreaElement`を指しています。なので`value`が必要であれば以下のようにすることで回避可能です。
```js
/** 省略 */
private _onInput(ev: Event):void {
console.log(this.value);
}
```
しかし、これはこれで問題があってTypeScriptの静的解析では`this`はクラスを指しているので、クラスに`value`がないというエラーが常に表示されます。
## 解決策
JavaScriptではES5からfunctionに変わり、アロー関数が追加されました。
アロー関数では従来のfunctionでは曖昧だった`this`を束縛することが可能です。
```js
/** 省略 */
private _onInput = (ev: Event):void => {
console.log(this._textarea.value);
}
```
アロー関数を使うことで`addEventListener`で変更されてしまった`this`をクラスのことであると束縛することができます。
## Vue.jsでの問題点
ここからが本題ですが、前回Vueを継承して補完を利かせるためにクラス構文を導入しました。
アロー関数を使うと、`this`は必ずクラスを指す。という考えの元メソッドはアロー関数で書いていたのですが、thisがクラスを指してしまう事によって、正しい処理が行われなくなりました。
```js
class Popup extends Vue {
private popup: HTMLElement = document.createElement("div");
/** comuted */
set element(el: HTMLElement | null) {
this.popup = el as HTMLElement;
}
/** methods */
hide = (): void => {
this.popup.style.display = 'none';
}
}
(() => {
const popup = new Popup();
popup.element = document.querySelector('#popup');
popup.hide();
}():
```
上記を実行するとsetしたHTMLではなく、メンバとして初期化したdivタグが`display: "none":`になります。
Vueを継承した場合、`this`は初期としてクラスを指しているのではなく、`VueComponent`を指していて`VueComponent`を通してでなければsetしたメンバの変更ができないようです。
`this`が何を指しているのかでメンバの変更がを受け付けるのかが変わっていて、現在大変苦戦しています。