在困难周期之前分配的变量。 javascript上的值已更改。但是dom方面的价值在循环结束时发生了变化。 无法显示加载div。 当循环继续时,如何显示加载div。
var vm = new Vue({
el: '#app',
data: {
loading: false,
},
methods: {
run() {
this.loading = true;
console.log(this.loading);
for (let i = 0; i < 1000000000; i++) {}
this.loading = false;
console.log(this.loading);
},
runWithAsync() {
vm.loading = true;
console.log(this.loading);
new Promise(function(resolve, reject) {
for (let i = 0; i < 1000000000; i++) {}
resolve(true);
}).then((result) => {
vm.loading = false;
console.log(this.loading);
})
},
runWithAsyncTimeout() {
this.loading = true;
console.log(this.loading);
setTimeout(function() {
new Promise(function(resolve, reject) {
for (let i = 0; i < 1000000000; i++) {}
resolve(true);
}).then((result) => {
this.loading = false;
console.log(this.loading);
})
}.bind(this), 100)
}
}
})
.loading {
width: 100%;
height: 100vh;
background: #ccc;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<div id="app">
<button @click="run">run</button>
<button @click="runWithAsync">runWithAsync</button>
<button @click="runWithAsyncTimeout">runWithAsyncTimeout</button>
<button @click="loading = !loading">change loading</button> {{ loading }}
<div class="loading" v-if="loading"></div>
</div>
答案 0 :(得分:3)
在考虑了一段时间之后,我想出了onRender
函数形式的 brillant 解决方案。
Vue有一个异步更新机制,您可以在使用Vue.nextTick
或vm.$nextTick
(视图模型实例函数)调整数据后等待。但是这会在DOM被更改但尚未呈现之后执行回调。如果你然后requestAnimationFrame
,你就会在下一次渲染之前结束。此时请求另一个动画帧将导致代码运行到下一帧渲染之前,所以最终会发生渲染:
// This is dumb.
const onRender = callback =>
Vue.nextTick(() =>
requestAnimationFrame(() =>
requestAnimationFrame(callback)));
var vm = new Vue({
el: '#app',
data: {
loading: false,
},
methods: {
run() {
this.loading = true;
console.log(this.loading);
onRender(() => {
for (let i = 0; i < 1000000000; i++) {}
this.loading = false;
console.log(this.loading);
});
}
}
})
.loading {
width: 100%;
height: 100vh;
background: #ccc;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<div id="app">
<button @click="run">run</button>
<button @click="loading = !loading">change loading</button> {{ loading }}
<div class="loading" v-if="loading"></div>
</div>
使用异步支持:
// Look at them arrows!
const onRender = (callback = () => {}) =>
new Promise(res =>
Vue.nextTick(() =>
requestAnimationFrame(() =>
requestAnimationFrame(() => res(callback())))));
var vm = new Vue({
el: '#app',
data: {
loading: false,
},
methods: {
async run() {
this.loading = true;
console.log(this.loading);
await onRender();
for (let i = 0; i < 1000000000; i++) {}
this.loading = false;
console.log(this.loading);
}
}
})
.loading {
width: 100%;
height: 100vh;
background: #ccc;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.min.js"></script>
<div id="app">
<button @click="run">run</button>
<button @click="loading = !loading">change loading</button> {{ loading }}
<div class="loading" v-if="loading"></div>
</div>