Vuetify执行大循环时如何提前显示v-progress-linear进度条
问题原因
- 现有代码执行顺序错误:
allRun方法中先执行了editorRun大循环,循环结束后才设置dialog = true,本身逻辑顺序就不符合预期 - JavaScript是单线程执行机制,同步代码会全部执行完成后才会触发DOM渲染更新。就算先修改了
dialog的显示状态,Vue的异步更新队列还没来得及把进度条渲染到页面上,大循环就会占住主线程,导致UI卡死直到循环结束才批量更新视图。
解决方法
调整执行顺序,设置进度条显示后,等待DOM更新完成再执行大循环,把循环逻辑放到异步任务队列中执行即可,修改后的核心代码如下:
<template> <div> <v-btn color="success" @click="allRun()" > 运行 </v-btn> <v-dialog v-model="dialog" hide-overlay persistent > <v-card color="primary" dark > <v-card-text> 请稍候 <v-progress-linear indeterminate ></v-progress-linear> </v-card-text> </v-card> </v-dialog> </div> </template> <script> export default { data () { return { dialog: false, listModes: [] // 你的原有业务数据 } }, methods: { allRun: function () { // 先触发进度条显示状态更新 this.dialog = true // 等待Vue完成DOM更新、进度条渲染完成后,再执行大循环 this.$nextTick(() => { // 用setTimeout把循环放到宏任务队列,避免阻塞当前UI渲染 setTimeout(() => { this.editorRun() }, 0) }) }, editorRun () { for (var i = 0; i < this.listModes.length; i++) { // 原有业务逻辑 } // 循环执行结束后关闭进度条 this.dialog = false } } } </script>
超大循环优化(可选)
如果你的循环数据量级特别大,单次执行时间超过100ms,就算显示了进度条也会因为主线程被占住出现动画卡顿,可以把循环拆成分批执行,每次处理部分数据后把控制权交还给UI渲染:
async editorRun () { const batchSize = 10 // 每次处理的数据条数,可根据实际业务调整 const total = this.listModes.length for (let i = 0; i < total; i += batchSize) { // 处理当前批次的数据 const end = Math.min(i + batchSize, total) for (let j = i; j < end; j++) { // 原有业务逻辑 } // 交还给浏览器渲染UI,避免进度条卡顿 await new Promise(resolve => requestAnimationFrame(resolve)) } this.dialog = false }
内容的提问来源于stack exchange,提问作者Ihar
相关产品推荐
相关产品推荐

