LoginSignup
52
30

More than 5 years have passed since last update.

Vueライフサイクルの盲点、computedの一発目の発火はmountedより早い

Posted at

TL;DR

https://jp.vuejs.org/v2/guide/instance.html#ライフサイクルダイアグラム
よく出てくるこの図ですが、computedって乗ってないんですよね。

さて、もうタイトルで語りたいこと90%くらい語ってるんですが、
要するにcomputedが最初に発火するとき、mountedまでに用意されない
ものを参照するとエラー吐くよ、という話です。

普通は遭遇しないと思いますが、一応…
(というかそういう事態に遭遇する時点で、VueをVueらしく使ってない可能性が高いです。)

例としてDOMのエレメントを$refを使って参照してみましょう。

template

<div id="app">
  <div ref="target">test!!</div>
  <div>{{ text }}</div>
</div>

js

var vm = new Vue({
  el: "#app",
  created() {
    console.log('----- created -----')
    console.log(this.$refs)
  },
  mounted() {
    console.log('----- mounted -----')
    console.log(this.$refs)
  },
  computed: {
    text() {
      console.log('----- computed -----')
      console.log(this.$refs)
    }
  }
});

結果

----- created -----
{}
----- computed -----
{}
----- mounted -----
{target: div}

computedが最初に実行されたとき、まだ$refの中身は空っぽですね。

あとがき

例として無理やり使いましたが、computedの中で$refはあまり使うべきではないです。
最初の発火時にDOMを発見できないですし、その後もリアクティブに発火しないですし…

そもそもcomputed内に限らず、公式でもあんまり$refつかうなよー、ってやんわり言ってますしね。

$refsはコンポーネントの描画後にデータが反映されるだけで、リアクティブではありません。子コンポーネントへの直接操作のための、退避用ハッチのような意味合いです(テンプレート内または算出プロパティから$refsにアクセスするのは避けるべきです)。

52
30
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
52
30