nextTickとは何ですか、またはVueJsでそれは何をしますか


104

ドキュメントを読みましたが、理解できません。私はどのデータ、計算、監視、メソッドが行うのか知っていますが、nextTick()vuejsで何が使用されますか?


17
理解すべき重要な概念は、DOMは非同期に更新されるということです。Vueで値を変更しても、変更はすぐにはDOM レンダリングされません。代わりに、VueはDOM更新をキューに入れ、タイマーでDOMを更新します。通常、これは非常に高速で行われるため、違いはありませんが、Vueがレンダリングした後、レンダリングされたDOMを更新する必要がある場合があります。更新が行われていないため、メソッドですぐに行うことはできません。まだ。そのような場合は、を使用しますnextTickここに文書化されています
Bert

上記のhttps://stackoverflow.com/q/47634258/9979046で @Bertが言ったことを補完するために、要素がDOM(HTML)に存在するかどうかを確認する必要がある場合は、ユニットテストでnextTick()を使用します。たとえば、 Axiosリクエストに関する情報を取得した場合。
オスカーアレンカー

回答:


138

nextTickを使用すると、データを変更し、VueJSがデータの変更に基づいてDOMを更新した後、ブラウザーがページ上の変更をレンダリングする前に何かを行うことができます。

通常、開発者はネイティブJavaScript関数setTimeoutを使用して同様の動作を実現します。ただし、setTimeoutコールバックを介して制御をユーザーに戻す前に、ブラウザへの制御を放棄します。

いくつかのデータを変更したとしましょう。Vueはデータに基づいてDOMを更新します。DOMの変更がブラウザによってまだ画面に表示されていないことに注意してください。を使用したnextTick場合、コールバックがすぐに呼び出されます。次に、ブラウザがページを更新します。を使用したsetTimeout場合、コールバックは今だけ呼び出されます。

この動作を視覚化するには、次のような小さなコンポーネントを作成します。

<template>
  <div class="hello">
    {{ msg }}
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data() {
    return {
        msg: 'One'
    }
  },
  mounted() {
      this.msg = 'Two';

      this.$nextTick(() => {
          this.msg = 'Three';
      });
  }
}
</script>

ローカルサーバーを実行します。表示Threeされているメッセージが表示されます。

今、あなたthis.$nextTicksetTimeout

setTimeout(() => {
    this.msg = 'Three';
}, 0);

ブラウザをリロードします。あなたが見るTwo前に、あなたは見るでしょうThree

このバイオリンをチェックして、ライブでご覧ください

これは、VueがDOMをTwoに更新し、ブラウザーを制御できるようになったためです。ブラウザが表示されましたTwo。次に、コールバックを呼び出しました。VueはDOMをに更新しましたThree。ブラウザが再表示したもの。

nextTick。VueはDOMをに更新しましたTwo。コールバックを呼び出しました。VueはDOMをに更新しましたThree。次に、ブラウザを制御しました。そして、ブラウザが表示されましたThree

それが明確だったと思います。

Vueがこれを実装する方法を理解するには、イベントループマイクロタスクの概念を理解する必要があります。

これらの概念を明確にしたら、nextTickのソースコードを確認してください。


4
私が理解していないことの1つは、「vueがデータを更新する」と言ったときに、exで作成された更新をthis.name = 'foo'参照しているのか、それともページ内のhtml要素の挿入を参照しているのか、ということです。
hidar

彼が「vueがデータを更新する」と言っているこの質問の履歴にはどこもありません...彼は「Vueはデータに基づいてDOMを更新する」と言っています。つまり、this.name = 'foo'vue を介してデータを設定すると、ドキュメントオブジェクトモデルが更新され、構成したテンプレートと機能に基づいてデータに加えられた変更が反映されます。
ADJenks

23

内容はから取られていることで・アドリアFontcuberta

Vueのドキュメントによると:

Vue.nextTick([コールバック、コンテキスト])

次のDOM更新サイクルの後に実行されるコールバックを延期します。一部のデータを変更した直後に使用して、DOMの更新を待ちます。

うーん...、最初は怖いと感じても、心配しないで、できるだけ簡単に説明しようと思います。ただし、最初に知っておくべきことが2つあります。

  1. その使用法はまれです。それらの銀の魔法カードの1つのように。私はいくつかのVueアプリを作成し、nextTick()に1回または2回実行しました。

  2. 実際の使用例を見れば、理解しやすくなります。アイデアを得ると、恐怖は消え、便利なツールがベルトの下にあります。

それならそれで行こう。

$ nextTickを理解する

私たちはプログラマーですね。最愛の分割統治アプローチを使用して、説明を.nextTick()少しずつ翻訳してみましょう。それでは始まります:

コールバックを延期する

OK、コールバックを受け入れることがわかりました。したがって、次のようになります。

Vue.nextTick(function () {
  // do something cool
});

すごい。このコールバックは、…まで延期されます(これはミレニアル世代が遅れると言う方法です)

次のDOM更新サイクル。

はい。VueがDOM更新を非同期で実行することはわかっています。それはそれらを適用する必要があるまでこれらの更新を「保存」しておく方法を備えています。更新のキューを作成し、必要に応じてフラッシュします。次に、DOMが「パッチ」され、最新バージョンに更新されます。

何?

もう一度試してみましょうthis.potatoAmount = 3.。Vueがコンポーネント(つまりDOM)を自動的に再レン​​ダリングしないように、コンポーネントが本当に不可欠でスマートなことを想像してください。必要な変更をキューに入れます。次に、次の「目盛り」(時計のように)でキューがフラッシュされ、更新が適用されます。多田!

はい!したがって、データが設定されてDOMが更新nextTick()された直後に実行されるコールバック関数を渡すために使用できることがわかります。

先ほど言ったように…それほど頻繁ではありません。Vue、React、およびGoogleからのもう1つのアプローチを駆動する「データフロー」アプローチは、言及しませんが、ほとんどの場合それを不要にします。ただし、場合によっては、DOMで一部の要素が表示/非表示/変更されるのを待つ必要があります。これはnextTickが便利になるときです。

一部のデータを変更した直後に使用して、DOMの更新を待ちます。

丁度!これは、Vueのドキュメントが提供した最後の定義です。コールバック内でDOMが更新されたため、「最も更新された」バージョンのDOMを操作できます。

証明する

よし、よし。コンソールを見ると、データの値がnextTickのコールバック内でのみ更新されていることがわかります。

const example = Vue.component('example', {
  template: '<p>{{ message }}</p>',
  data: function () {
    return {
      message: 'not updated'
    }
  },
  mounted () {
    this.message = 'updated'

        console.log(
        'outside nextTick callback:', this.$el.textContent
    ) // => 'not updated'

    this.$nextTick(() => {
      console.log(
        'inside nextTick callback:', this.$el.textContent
      ) // => 'not updated'
    })
  }
})


new Vue({
  el: '#app',
    render: h => h(example)
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.10/vue.js"></script>
<div id="app"></div>

ユースケース

の便利な使用例をいくつか定義してみましょうnextTick

コンポーネントがマウントされたときに何らかのアクションを実行する必要があると想像してください。だが!コンポーネントだけではありません。また、すべての子がマウントされてDOMで使用できるようになるまで待機する必要があります。くそー!マウントされたフックは、コンポーネントツリー全体がレンダリングされることを保証しません。

次のDOM更新サイクルを待つツールさえあれば…

ははは:

mounted() {
  this.$nextTick(() => {
    // The whole view is rendered, so I can safely access or query
    // the DOM. ¯\_(ツ)_/¯
  })
}

一言で言えば

したがってnextTick、データが設定され、DOMが更新された後に関数を実行する快適な方法です。

DOMを待つ必要があります。何らかの変換を実行する必要があるためか、外部ライブラリがそのデータをロードするのを待つ必要があるためでしょうか。次にnextTickを使用します。

一部の人々はまた、データが更新されたことを確認する方法として、ユニットテストでnextTickを使用しています。このようにして、コンポーネントの「更新されたバージョン」をテストできます。

Vue.nextTick()またはvm。$ nextTick()?

心配しないでください。どちらも(ほとんど)同じです。Vue.nextTick()vm.$nextTick()インスタンスAPIですが、グローバルAPIメソッドを指します。唯一の違いはvm.$nextTick、2番目のパラメーターとしてコンテキストを受け入れないことです。常にバインドさthisれています(インスタンス自体とも呼ばれます)。

最後のクールさ

がをnextTick返すことPromiseに注意してください。そうすればasync/await、例を完全に使用して改善することができます。

async mounted () {
    this.message = 'updated'
    console.log(this.$el.textContent) // 'not updated'
    await this.$nextTick()
    console.log(this.$el.textContent) // 'updated'
}

2
「あなたの」説明の上部に、元の著者とリンクを追加するだけです。
Renan Cidale

1
なんて素晴らしい説明でしょう!お忙しいところありがとうございました。
Muaath Alhaddad

16

Next Tickは基本的に、リアクティブプロパティ(データ)にいくつかの変更を加えたときに、Vueがコンポーネントを再レンダリングした後、いくつかのコードを実行することを可能にします。

// modify data
vm.msg = 'Hello'
// DOM not updated yet
Vue.nextTick(function () {
  // this function is called when vue has re-rendered the component.
})

// usage as a promise (2.1.0+, see note below)
Vue.nextTick()
  .then(function () {
      // this function is called when vue has re-rendered the component.
})

Vue.jsドキュメントから:

次のDOM更新サイクルの後に実行されるコールバックを延期します。一部のデータを変更した直後に使用して、DOMの更新を待ちます。

詳細については、こちらをご覧ください


2
それをどのように更新しますか?これは私が理解していないことです。vm.msgを更新すると、新しいテキスト '' hello "があるのでdomはすでに更新されています..どうすれば再び更新できますか?例のフィドルでフィドルを投稿できますか?感謝
hidar

さて、私は答えを編集し、それをさらに説明しようとします。
Daksh Miglani 2017

@hidar複数の更新を行う必要があるが、異なるdomサイクルで互いに明示的にレンダリングしたい場合に使用できます
Daksh Miglani

更新できるようにするためではありませんは、DOM自体、Vueによって行われた変更によって影響を受けた/変更された後は、DOMで何かを行う(更新、情報の読み取りなど)ためです(リアクティブプロパティの値を変更したため) 、など)。
zenw0lf 2018年

それはそれをより簡単にするための例でした。
Daksh Miglani

7

nextTickとsetTimeoutを使用することの違いについて、Pranshatの答えを明確にするために、私は彼のフィドルを分岐しました: ここ

mounted() {    
  this.one = "One";
 
  setTimeout(() => {
    this.two = "Two"
  }, 0);
  
  //this.$nextTick(()=>{
  //this.two = "Two"
  //})}

フィドルでは、setTimeOutを使用する場合、変更を適用する前にコンポーネントがマウントされると、初期データがごく短時間点滅することがわかります。一方、nextTickを使用する場合、データはブラウザーにレンダリングされる前にハイジャックされ、変更されます。そのため、ブラウザは古いデータを知らなくても、更新されたデータを表示します。2つの概念が一挙にクリアされることを願っています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.