2020-04-19

【Vue.js】methods,computed内部でアロー関数を使ってはいけない

文法は間違っていないのに変数にアクセスしようとするとundefinedとなるので注意。

Article Image

先に結論

methods, computed等の中の関数をアロー関数(アローファンクション)にしてはいけない。

前提

  1. vueのバージョン 2.6.11

    ※vueのバージョン確認はnpm list vue

  2. vue.cliは 4.2.3

  3. データにアクセスしようとするとundefinedになる不具合

問題ないコード

次のコードは問題ない。

data部の外側の定義はアローファンクションを使っても良い。これが混乱を招く。

export default {
  data: () => ({ //アローファンクションで定義
    message_data: "ok" 
  }),
  methods: {
    test() {
      console.log(this.message_data)
    }
  },
  
  // 実行結果
  // ok

アロー関数とはES6から実装された文法でここではメソッドの定義に使用している。

data: function(){} とするところを data: () => {} と記述してよい。

ES6にてオブジェクトにメソッドを割り当てる場合アローファンクションを使っても良いというのを経験上知っている。ただ、JS公式の「メソッド定義」にはこの方法は書いていないのでもしかしたら間違っているのだろうか。

Node.jsにて次のコードが正しく動作することを検証した。

//es6を使うので拡張子はmjs
const A = {
    tes_string: "ok",
    myFunc: () => { //ここがアロー関数
        console.log(A.tes_string)
    }
}

A.myFunc()

// 実行結果
// ok

エラーとなるコード

Vue.jsにて。次のコードはビルドエラーにはならないが実行時にエラーとなる。

export default {
  data: () => ({
    message_data: "ok"
  }),
  methods: {
    test() {
      console.log(this.testComputed) //computed越しにmessage_dataを表示
    }
  },
  computed: {
    testComputed:() => { //問題のコード。アロー関数で定義されている
      return this.message_data
    }
  }
}

//実行結果
//TypeError: Cannot read property 'message_data' of undefined

これはコンパイル時にはエラーにならない。

私はこの問題に悩まされたが次のフォーラムにたどり着いて解決した

英語:VueJS: variable is undefined inside computed only

正しいコード

念の為正しいコードを提示する。

<script>
export default {
  data: () => ({
    message_data: "ok"
  }),
  methods: {
    test() {
      console.log(this.testComputed)
    }
  },
  computed: {
    testComputed(){ //ここを修正
      return this.message_data
    }
  }
}
</script>

// 実行結果
// ok

追加の情報

Don't use arrow function ()=>{} for computed, it will cause the wrong context (not current Vue instance).

Change to function () {} then it should work fine.

And for methods, watch, you should follow same rules.

先程のフォーラムの指摘箇所原文。強調した箇所によるとmethodswatchなどでも同様のことが言えるらしい。

今までこの問題にぶち当たらなかったのはmethodscomputed内では キー名: function() ~~ ではなく 関数名() でいきなり書き始められるからだ。これはNode.jsも同様で正しく動作する。

  methods: {
    test() { //これで良い
      console.log(this.testComputed)
    }
  }

Vue.jsの公式コードがこの部分をキーと値の書式で記述している。これによりドキュメントを何気に参照したのち手癖でアローファンクションにしてしまった。

次が公式の書式

methods: {
  reverseMessage: function () { 
    return this.message.split('').reverse().join('')
  }
}

//アローファンクションではないが : を使ってキー名:値のような書式になっている
//当然 reverseMessage: () => {  でも動作すると考えてもおかしくない

所感

Vue.jsのデメリットではあるが加えてJavaScriptのデメリットに出会った気がする。定義方法が曖昧だ。

おまけ

今の所予定はないがGitHub最近はReactも学習して良いかなと考え始めた。

npmtrends.comによるVue.jsとReact.jsのDL数比較を参考に出しておく。

2020 04 20 01h22 57

2020 04 20 01h25 23

スター数ではVueに軍配があがるが、DL数で見るとReactの伸びが圧倒的になっている。



この記事のタグ

この記事をシェア


謎の技術研究部 (謎技研)