我想强制 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>
Run Code Online (Sandbox Code Playgroud)
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';
});
}
Run Code Online (Sandbox Code Playgroud)
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>
Run Code Online (Sandbox Code Playgroud)
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';
}
Run Code Online (Sandbox Code Playgroud)
v-bind:key似乎也没有做任何事情:
vm.$el。代码笔: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>
Run Code Online (Sandbox Code Playgroud)
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';
}
Run Code Online (Sandbox Code Playgroud)
正如这个流行的答案所推荐的那样,使用计算属性似乎也没有做任何事情:
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>
Run Code Online (Sandbox Code Playgroud)
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';
}
Run Code Online (Sandbox Code Playgroud)
使用 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>
Run Code Online (Sandbox Code Playgroud)
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';
});
}
Run Code Online (Sandbox Code Playgroud)
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>
Run Code Online (Sandbox Code Playgroud)
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);
}
Run Code Online (Sandbox Code Playgroud)
Vue.nextTick, vm.$forceUpdate, v-bind:key, 或计算属性不起作用?setTimeout在延迟时工作不一致0?setTimeout似乎哈克。是否有一种“适当”的方式来强制 UI 更新?B未在 UI 中更新/显示的错觉是由 Vue 的 Async Update Queue 和 JavaScript 的 Event Loop Process 模型组合引起的。有关详细信息和证明,请继续阅读。
这些实际上做你想做的(但似乎没有)
Vue.nextTicksetTimeout - (但似乎没有短暂的超时)这些按预期工作(但需要解释)
v-bind:keyvm.$forceUpdate注意:上面的但似乎没有表示 Vue 正在做它应该做的事情,但没有出现预期的视觉输出。因此,代码不会产生准确的预期输出。
前两个作品
证明前两个做你想做的事情很容易。'B' 没有被放置在视图中的想法将被反驳。但需要进一步讨论以解决缺乏明显变化的问题。
vue.js在第 1789 行设置断点当您逐步执行序列时,您会注意到 UI 更新为值“B”(无论超时长度如何)。驱散。
那么缺乏能见度怎么办?这是由 JavaScript 的Event Loop流程模型引起的,具体与一个称为 Run-to-Completion 的原则有关。该MDN事件循环文档状态:
这种模型的一个缺点是,如果一条消息需要很长时间才能完成,Web 应用程序将无法处理用户交互,如单击或滚动。
或运行渲染/绘制浏览器进程。因此,当执行堆栈时,B会C立即渲染,然后立即渲染,这似乎B从未渲染过。当使用带有 JavaScript 繁重任务(例如引导 SPA)的动画 GIF 时,可以看到这个确切的问题。动画 GIF 要么会断断续续,要么根本不会动画 - 运行到完成阻碍了。
所以 Vue 做它应该做的事情,而 JavaScript 做它应该做的事情。但是长时间运行的循环很麻烦。这就是 lodash_debounce或 simplesetTimout等工具有用的原因。
最后三个工作?
是的。使用相同的断点vue.js将显示 Vue 刷新其更新队列时发生的唯一中断。正如Vue 关于异步更新队列的文档中所讨论的,每个更新都会排队,并且只呈现每个属性的最后一次更新。因此,尽管在处理过程中message实际更改为B,但由于 Vue 异步队列的工作方式,它永远不会呈现:
如果您还没有注意到,Vue 会异步执行 DOM 更新。每当观察到数据更改时,它将打开一个队列并缓冲在同一事件循环中发生的所有数据更改。
| 归档时间: |
|
| 查看次数: |
2149 次 |
| 最近记录: |