LoginSignup
0
0

More than 1 year has passed since last update.

【Vue.js】methods内で時間のかかる処理をawaitすると変数のビューへの反映が思ったタイミングより遅いことがある

Last updated at Posted at 2021-07-16

起きること

samplecomponent.vue
<template>
  <div>
    <!-- var1の値が変更されるたびリアクティブに表示も変更されるはず -->
    <p>{{ var1 }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      var1: "oldvalue",
      var2: "piyopiyo"
    };
  },

  methods: {
    hoge() {
      // 1. 変数`var1`を変更する => この時点で表示は変わってほしい
      this.var1 = "newvalue";
      // 2. 時間のかかる処理`heavyProcess()`を待ち、その結果を使って後続の処理を行う(たとえばここではif())
      if (await heavyProcess()) {
        // 3. 後続処理
        this.var2 = "piyo";
      }
    }
  }
</script>

想定するのは...

awaitより前でvar1を変更しているので、 2 や 3 を待つことなくビューは変更されnewvalueと表示されている気がする。

実際には...

hoge()が終わった時点で表示が変わる。

なぜ?

データ変更が検出されると、Vue はキューをオープンし、同じイベントループで起こる全てのデータ変更をバッファリングします。

methods に定義した関数や mounted() など一つのイベントループとみなされる処理の中で複数の変数を変更するとき、それらの変更は個別にビューに反映されるのではなく、次の "tick" が来るときにまとめて反映が始まる。

つまり一つの処理内で変数var1を変更=>何らかをawaitやthen()=>変数var2を変更とすると、var1の変更がビューに反映されるのはvar2の変更を待ってからになる。

どうすればいい?

データの変更後に Vue.js の DOM 更新の完了を待つには、データが変更された直後に Vue.nextTick(callback) を使用することができます。そのコールバックは DOM が更新された後に呼ばれます。

Vue.nextTick()を利用して強制的にDOM更新を挟むことができる。

samplecomponent.vue
<script>
export default {
  data() {
    return {
      var1: "oldvalue",
      var2: "piyopiyo"
    };
  },

  methods: {
    hoge() {
      // 1. 変数`var1`を変更する => この時点で表示も変わってほしい
      this.var1 = "newvalue";
      // α. DOM更新を起こす
      this.$nextTick(() => {
        // nextTick()のコールバックはDOM更新を待って実行が始まる

        // 2. 時間のかかる処理`heavyProcess()`を待ち、その結果を使って後続の処理を行う(たとえばここではif())
        if (await heavyProcess()) {
          // 3. 後続処理
          this.var2 = "piyo";
        }
      });
    }
  }
</script>

こうすれば、 2 や 3 はビューに 1 の結果が反映されてから実行される。

おまけ

なお、nextTick()はPromiseを返すので、await や then() でより直感的に書くこともできる。

await this.$nextTick();
// DOM更新後に行いたい処理
this.$nextTick().then(() => {
  // DOM更新後に行いたい処理
});
0
0
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
0
0