イベントループサイクルの途中でUIを強制的に更新したいと思います。
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.$el
。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もまったく何もしていないようです:
vm.$el
。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';
}
この一般的な回答が推奨するように、計算されたプロパティを使用しても、何もしないようです。
vm.$el
。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
動作しているように見える唯一のものです。ただし、遅延が100
。の場合にのみ一貫して機能します。遅延がの場合、0
動作することがありますが、一貫して動作しません。
vm.$el
更新。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);
}
Vue.nextTick
、vm.$forceUpdate
、v-bind:key
、またはプロパティの仕事を計算?setTimeout
遅延がであるのに、なぜ一貫性のない動作をするの0
ですか?setTimeout
ハッキーのようです。UIの更新を強制する「適切な」方法はありますか?B
UIで更新/表示されないという錯覚は、Vueの非同期更新キューとJavaScriptのイベントループプロセスモデルの組み合わせによって引き起こされます。詳細と校正については、以下をお読みください。
これらは、実際に行うあなたが望むもの(ただし、していないようです)
Vue.nextTick
setTimeout
-(ただし、タイムアウトが短いようには見えません)これらは期待どおりに機能します(ただし、説明が必要です)
v-bind:key
vm.$forceUpdate
注:上記のようには見えませんが、Vueが想定どおりに動作していることを確認していますが、期待されるビジュアル出力が表示されません。したがって、コードは期待どおりの出力を生成しません。
最初の2つの作業
最初の2つがあなたが望むことをすることを証明することは非常に簡単です。'B'がビューに配置されないという考えは反証されます。しかし、目に見える変化の欠如に対処するには、さらなる議論が必要です。
vue.js
1789行目にブレークポイントを設定しますシーケンスをステップ実行している間、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]
コメントを追加