要:
在发出事件时显示HTML元素,并在显示该元素后运行一些计算。
但是:
HTML元素仅在计算运行后显示。
奇怪:
控制台显示事件回调在计算之前运行。
let app = new Vue({
el: '#app',
data: {
show: false
},
methods: {
showCallback() {
console.log('showCallback');
console.log(this.show);
this.show = true;
console.log(this.show);
},
start() {
this.$emit('loading-show');
console.log('Calculation start');
// Do some calculations
for (let i = 1; i < 10000000000; i++) {}
console.log('Calculation finish');
}
},
mounted() {
this.$on('loading-show', this.showCallback);
},
destroyed() {
this.$off('loading-show', this.showCallback);
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<button @click="start">Start</button>
<h1 v-show="show">Shown</h1>
</div>
答案 0 :(得分:2)
您不应在测试中使用for循环,而应使用setTimeout。否则,您的用户界面将不会更新。
使用v-if
,v-else-if
和v-else
根据您的状态显示HTML。
let app = new Vue({
el: '#app',
data: {
show: false,
done: false,
showCallback: function() {
console.log('showCallback');
console.log(this.show);
this.show = true;
console.log(this.show);
}
},
methods: {
start() {
this.done = false
this.$emit('loading-show');
console.log('Calculation start');
// Do some calculations
setTimeout(()=>{
this.done = true
console.log('Calculation finish');}, 2000)
}
},
mounted() {
this.$on('loading-show', this.showCallback);
},
destroyed() {
this.$off('loading-show', this.showCallback);
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<button @click="start">Start</button>
<h1 v-if=!show>Press Start</h1>
<h1 v-else-if="!done">Processing</h1>
<h1 v-else>Shown</h1>
</div>
答案 1 :(得分:0)
await vm.$nextTick();
-然后给浏览器喘口气requestAnimationFrame
发出事件后,更新dom,并在进行任何形式的阻塞之前跳过渲染帧。
应该总是做-考虑到低计算设备。
Vue.skipFrame = function(){
return new Promise(resolve => {
requestAnimationFrame(() =>
requestAnimationFrame(resolve)
)
})
}
let app = new Vue({
el: '#app',
data: {
show: false
},
methods: {
showCallback(ctx) {
console.log('showCallback');
console.log(this.show);
this.show = true;
console.log(this.show);
},
async start() {
this.$emit('loading-show', this);
console.log('Calculation start');
await this.$nextTick();
// dom is up to date now and has to be painted
// thus skip one frame before blocking the browser in the second
await Vue.skipFrame();
for (let i = 1; i < 1000000000; i++) {
}
console.log('Calculation finish');
}
},
mounted() {
this.$on('loading-show', this.showCallback);
},
destroyed() {
this.$off('loading-show', this.showCallback);
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<button @click="start">Start</button>
<h1 v-show="show">Shown</h1>
</div>