Vue.jsのイベントループサイクルの途中でUIを強制的に更新するにはどうすればよいですか?

アダム・ザーナー

イベントループサイクルの途中でUIを強制的に更新したいと思います。

Vue.nextTick

Vue.nextTickはの更新バージョンを提供しているようですが、vm.$el実際にはUIを更新しません。

CodePen:https://codepen.io/adamzerner/pen/RMexgJ?editors = 1010

HTML:

<div id="example">
  <p>Value: {{ message }}</p>
  <button v-on:click="change()">Change</button>
</div>

JS:

var vm = new Vue({
  el: '#example',
  data: {
    message: 'A'
  },
  methods: {
    change: change
  }
})

function change () {
  vm.message = 'B';
  // vm.$el.children[0].textContent === "Value: A"
  Vue.nextTick(function () {
    // vm.$el.children[0].textContent === "Value: B"
    // but the UI hasn't actually updated
    for (var i = 0; i < 10000000; i++) {}
    vm.message = 'C';
  });
}

vm。$ forceUpdate

vm。$ forceUpdateは何もしていないようです。

  1. の値は変更されていないようですvm.$el
  2. UIを更新していないようです。

CodePen:https://codepen.io/adamzerner/pen/rdqpJW?editors = 1010

HTML:

<div id="example">
  <p>Value: {{ message }}</p>
  <button v-on:click="change()">Change</button>
</div>

JS:

var vm = new Vue({
  el: '#example',
  data: {
    message: 'A'
  },
  methods: {
    change: change
  }
})

function change () {
  vm.message = 'B';
  // vm.$el.children[0].textContent === "Value: A"
  vm.$forceUpdate();
  // vm.$el.children[0].textContent === "Value: A" still
  // and the UI hasn't actually updated
  for (var i = 0; i < 10000000; i++) {}
  vm.message = 'C';
}

v-bind:key

v-bind:keyもまったく何もしていないようです:

  1. の値は変更されていないようですvm.$el
  2. UIを更新していないようです。

Codepen:https://codepen.io/adamzerner/pen/WzadKN?editors = 1010

HTML:

<div id="example">
  <p v-bind:key="message">Value: {{ message }}</p>
  <button v-on:click="change()">Change</button>
</div>

JS:

var vm = new Vue({
  el: '#example',
  data: {
    message: 'A'
  },
  methods: {
    change: change
  }
})

function change () {
  // vm.$el.children[0].textContent === "Value: A"
  vm.message = 'B';
  // vm.$el.children[0].textContent === "Value: A" still
  // and the UI hasn't actually updated
  for (var i = 0; i < 10000000; i++) {}
  vm.message = 'C';
}

計算された

この一般的な回答が推奨するように、計算されたプロパティを使用しても、何もしないようです。

  1. の値は変更されていないようですvm.$el
  2. UIを更新していないようです。

CodePen:https://codepen.io/adamzerner/pen/EEdoeX?editors = 1010

HTML:

<div id="example">
  <p>Value: {{ computedMessage }}</p>
  <button v-on:click="change()">Change</button>
</div>

JS:

var vm = new Vue({
  el: '#example',
  data: {
    message: 'A'
  },
  computed: {
    computedMessage: function () {
      return this.message;
    },
  },
  methods: {
    change: change
  }
})

function change () {
  // vm.$el.children[0].textContent === "Value: A"
  vm.message = 'B';
  // vm.$el.children[0].textContent === "Value: A" still
  // and the UI hasn't actually updated
  for (var i = 0; i < 10000000; i++) {}
  vm.message = 'C';
}

約束(編集で追加)

promiseの使用も機能しません。

CodePen:https://codepen.io/adamzerner/pen/oqaEpV?editors = 1010

HTML:

<div id="example">
  <p>Value: {{ message }}</p>
  <button v-on:click="change()">Change</button>
</div>

JS:

var vm = new Vue({
  el: '#example',
  data: {
    message: 'A'
  },
  methods: {
    change: change
  }
})

function change () {
  // vm.$el.children[0].textContent === "Value: A"
  vm.message = 'B';
  // vm.$el.children[0].textContent === "Value: A" still
  // and the UI hasn't actually updated
  var promise = new Promise(function (resolve, reject) {
    for (var i = 0; i < 10000000; i++) {}
    resolve();
  });
  promise.then(function () {
    vm.message = 'C';
  });
}

setTimeout

setTimeout動作しているように見える唯一のものです。ただし、遅延が100。の場合にのみ一貫して機能します遅延がの場合、0動作することがありますが、一貫して動作しません。

  1. vm.$el 更新。
  2. UIが更新されます。

CodePen:https://codepen.io/adamzerner/pen/PRyExg?editors = 1010

HTML:

<div id="example">
  <p>Value: {{ message }}</p>
  <button v-on:click="change()">Change</button>
</div>

JS:

var vm = new Vue({
  el: '#example',
  data: {
    message: 'A'
  },
  methods: {
    change: change
  }
})

function change () {
  // vm.$el.children[0].textContent === "Value: A"
  vm.message = 'B';
  setTimeout(function () {
    // vm.$el.children[0].textContent === "Value: B"
    // the UI has updated
    for (var i = 0; i < 10000000; i++) {}
    vm.message = 'C';
  }, 100);
}

質問

  1. なぜいないVue.nextTickvm.$forceUpdatev-bind:key、またはプロパティの仕事を計算?
  2. setTimeout遅延がであるのに、なぜ一貫性のない動作をするの0ですか?
  3. setTimeoutハッキーのようです。UIの更新を強制する「適切な」方法はありますか?
ランディキャスバーン

あらすじ

BUIで更新/表示されないという錯覚は、Vueの非同期更新キューとJavaScriptのイベントループプロセスモデルの組み合わせによって引き起こされます。詳細と校正については、以下をお読みください。

調査結果の要約

これらは、実際に行うあなたが望むもの(ただし、していないようです)

  • Vue.nextTick
  • setTimeout -(ただし、タイムアウトが短いようには見えません)

これらは期待どおりに機能します(ただし、説明が必要です)

  • v-bind:key
  • vm.$forceUpdate
  • 約束する

注:上記のようには見えませんが、Vueが想定どおりに動作していることを確認していますが、期待されるビジュアル出力が表示されません。したがって、コードは期待どおりの出力を生成しません

討論

最初の2つの作業

最初の2つあなたが望むことをすることを証明することは非常に簡単です。'B'がビューに配置されないという考えは反証されます。しかし、目に見える変化の欠如に対処するには、さらなる議論が必要です。

  • Chromeで各ペンを開きます
  • 開発ツールで、vue.js1789行目にブレークポイントを設定します
  • シーケンスをステップスルーする

シーケンスをステップ実行している間、UIが値「B」で更新されていることに気付くでしょう(タイムアウトの長さに関係なく)。払拭。

では、可視性の欠如はどうですか?これはJavaScriptのイベントループプロセスモデルが原因であり、特にRun-to-Completionと呼ばれる原則に関連しています。MDNイベントループのドキュメントの状態:

このモデルの欠点は、メッセージの完了に時間がかかりすぎると、Webアプリケーションがクリックやスクロールなどのユーザー操作を処理できないことです。

または、レンダリング/ペイントブラウザプロセスを実行します。したがって、スタックが実行されると、BそのC直後にレンダリングされますが、これBは決してレンダリングされないようです。SPAのブートストラップなど、JavaScriptの重いタスクでアニメーションGIFを使用すると、この正確な問題が発生する可能性があります。アニメーションGIFは途切れるか、まったくアニメーション化されません。Run-to-Completionが邪魔になります。

したがって、Vueは想定されていることを実行し、JavaScriptは想定されていることを正しく実行します。しかし、長時間実行されるループは面倒です。これが、lodash_debounceやsimplesetTimoutなどのツールが役立つ理由です。

最後の3つの仕事?

はい。で同じブレークポイントを使用するとvue.js、Vueが更新のキューをフラッシュしているときに発生する唯一のブレークが表示さます。非同期更新キューに関するVueのドキュメントで説明されているように、各更新はキューに入れられ、各プロパティの最後の更新のみがレンダリングされます。したがって、message実際にBは処理中にに変更されますが、Vue非同期キューの動作方法のためにレンダリングされることはありません。

まだ気付いていない場合は、VueはDOMの更新を非同期で実行します。データの変更が観察されるたびに、キューが開かれ、同じイベントループで発生するすべてのデータの変更がバッファリングされます。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

ホットリロードイベントごとにブラウザのJavascriptコンソールをクリアするようにVue.jsサイトを設定するにはどうすればよいですか?

分類Dev

Vueループの最初のアイテムにイベントハンドラーを追加するにはどうすればよいですか?

分類Dev

Vue.jsコンポーネントのスタイルの範囲を制限するにはどうすればよいですか?

分類Dev

Vueファイルのスクリプトセクションを別のファイルに分離するにはどうすればよいですか?

分類Dev

ant design vue table列のタイトルをクリックしてイベントを追加するにはどうすればよいですか?

分類Dev

Vue JS:ルーターリンクでアクティブな<a>タグのスタイルを設定するにはどうすればよいですか?

分類Dev

vue.jsプロジェクトのmain.jsファイルにjsクラスをインポートし、各コンポーネントにインポートするのではなく、すべてのコンポーネントで使用するにはどうすればよいですか?

分類Dev

VueプロジェクトでThree.jsモジュールを正しくインポートするにはどうすればよいですか?

分類Dev

Vue.jsルータービューコンポーネント間でイベントを発行するにはどうすればよいですか?

分類Dev

vue.jsのページを更新せずに現在のタイムスタンプを更新するにはどうすればよいですか?

分類Dev

Vue.jsのBootstrap-Vue <b-nav-item-dropdown>でクリックイベントを使用するにはどうすればよいですか?

分類Dev

vue.js forループ要素のインデックスにアクセスするにはどうすればよいですか?

分類Dev

ネイティブイベントでVueルーターをプログラムで使用するにはどうすればよいですか?

分類Dev

vueコンポーネントから通常のjsファイルのデータ値を取得するにはどうすればよいですか?

分類Dev

Vueコンポーネントのスコープスタイルをオーバーライドするにはどうすればよいですか?

分類Dev

自分のクラスまたはメソッドをVueでグローバルにインポートするにはどうすればよいですか?

分類Dev

Vuexアクションが完了する前にVueライフサイクルの進行を停止するにはどうすればよいですか?

分類Dev

vue jsのログインコンポーネントからユーザーの状態を更新するにはどうすればよいですか?

分類Dev

Laravelのapp.jsファイルにVueコンポーネントを追加するにはどうすればよいですか?

分類Dev

Vue CLI 3でvueルータープラグインをインストールするにはどうすればよいですか?

分類Dev

グローバルイベント処理用のVueバスを作成するにはどうすればよいですか?

分類Dev

Vue.jsのボタンクリックイベントでテキストフィールドを有効にするにはどうすればよいですか?

分類Dev

vue.jsでボタンを1行に強制するにはどうすればよいですか?

分類Dev

vue-tel-inputのイベントを使用するにはどうすればよいですか?

分類Dev

ubuntu に vue/cli をインストールするにはどうすればよいですか?

分類Dev

Vue js SPAをDjangoサーバーにデプロイするにはどうすればよいですか?

分類Dev

同じ名前のコンポーネントをVueルーターにインポートするにはどうすればよいですか

分類Dev

BootstrapVueを使用してVueのリソースタイムラインのフルカレンダーイベントにポップオーバーを追加するにはどうすればよいですか?

分類Dev

element-ui(vue.js)のテーブルヘッダーにツールチップを追加するにはどうすればよいですか?

Related 関連記事

  1. 1

    ホットリロードイベントごとにブラウザのJavascriptコンソールをクリアするようにVue.jsサイトを設定するにはどうすればよいですか?

  2. 2

    Vueループの最初のアイテムにイベントハンドラーを追加するにはどうすればよいですか?

  3. 3

    Vue.jsコンポーネントのスタイルの範囲を制限するにはどうすればよいですか?

  4. 4

    Vueファイルのスクリプトセクションを別のファイルに分離するにはどうすればよいですか?

  5. 5

    ant design vue table列のタイトルをクリックしてイベントを追加するにはどうすればよいですか?

  6. 6

    Vue JS:ルーターリンクでアクティブな<a>タグのスタイルを設定するにはどうすればよいですか?

  7. 7

    vue.jsプロジェクトのmain.jsファイルにjsクラスをインポートし、各コンポーネントにインポートするのではなく、すべてのコンポーネントで使用するにはどうすればよいですか?

  8. 8

    VueプロジェクトでThree.jsモジュールを正しくインポートするにはどうすればよいですか?

  9. 9

    Vue.jsルータービューコンポーネント間でイベントを発行するにはどうすればよいですか?

  10. 10

    vue.jsのページを更新せずに現在のタイムスタンプを更新するにはどうすればよいですか?

  11. 11

    Vue.jsのBootstrap-Vue <b-nav-item-dropdown>でクリックイベントを使用するにはどうすればよいですか?

  12. 12

    vue.js forループ要素のインデックスにアクセスするにはどうすればよいですか?

  13. 13

    ネイティブイベントでVueルーターをプログラムで使用するにはどうすればよいですか?

  14. 14

    vueコンポーネントから通常のjsファイルのデータ値を取得するにはどうすればよいですか?

  15. 15

    Vueコンポーネントのスコープスタイルをオーバーライドするにはどうすればよいですか?

  16. 16

    自分のクラスまたはメソッドをVueでグローバルにインポートするにはどうすればよいですか?

  17. 17

    Vuexアクションが完了する前にVueライフサイクルの進行を停止するにはどうすればよいですか?

  18. 18

    vue jsのログインコンポーネントからユーザーの状態を更新するにはどうすればよいですか?

  19. 19

    Laravelのapp.jsファイルにVueコンポーネントを追加するにはどうすればよいですか?

  20. 20

    Vue CLI 3でvueルータープラグインをインストールするにはどうすればよいですか?

  21. 21

    グローバルイベント処理用のVueバスを作成するにはどうすればよいですか?

  22. 22

    Vue.jsのボタンクリックイベントでテキストフィールドを有効にするにはどうすればよいですか?

  23. 23

    vue.jsでボタンを1行に強制するにはどうすればよいですか?

  24. 24

    vue-tel-inputのイベントを使用するにはどうすればよいですか?

  25. 25

    ubuntu に vue/cli をインストールするにはどうすればよいですか?

  26. 26

    Vue js SPAをDjangoサーバーにデプロイするにはどうすればよいですか?

  27. 27

    同じ名前のコンポーネントをVueルーターにインポートするにはどうすればよいですか

  28. 28

    BootstrapVueを使用してVueのリソースタイムラインのフルカレンダーイベントにポップオーバーを追加するにはどうすればよいですか?

  29. 29

    element-ui(vue.js)のテーブルヘッダーにツールチップを追加するにはどうすればよいですか?

ホットタグ

アーカイブ