加载状态的最小展示时间怎么控制才不闪屏?

一鸣 阅读 27

我在做列表数据加载时,加了个 loading 状态,但数据回来太快的话 loading 一闪而过,用户根本看不清,体验很怪。有没有办法让 loading 至少显示 300ms 再消失?

我试过用 setTimeout 延迟更新状态,但和实际请求时间不好协调,有时候反而更慢了。下面是我现在的 loading 结构:

<div v-if="loading" class="loading-mask">
  <span>加载中...</span>
</div>
<ul v-else>
  <li v-for="item in list" :key="item.id">{{ item.name }}</li>
</ul>
我来解答 赞 8 收藏
二维码
手机扫码查看
2 条解答
司马焕焕
为了确保 loading 状态至少显示 300ms 而不与实际请求时间冲突,可以使用 Promise 和 setTimeout 结合的方式来处理。具体来说,你可以创建一个函数来管理这个逻辑,保证 loading 状态至少持续 300ms。下面是一个简单的实现:

首先,假设你有一个获取数据的方法 fetchData,你需要改造它以确保 loading 状态的最小展示时间。

// 假设 fetchData 是你的数据获取方法
async function fetchData() {
// 模拟请求,实际应用中替换为 axios 或其他请求库
return new Promise(resolve => setTimeout(() => resolve([{ id: 1, name: 'Item 1' }, { id: 2, name: 'Item 2' }]), 200));
}

let loading = false;
let list = [];

async function loadList() {
loading = true;

const startTime = Date.now();

// 同时发起请求和定时器
const dataPromise = fetchData();
const timerPromise = new Promise(resolve => setTimeout(resolve, 300));

// 等待两者都完成
await Promise.all([dataPromise, timerPromise]);

// 计算请求耗时,并决定是否需要额外等待
const elapsedTime = Date.now() - startTime;
if (elapsedTime < 300) {
// 请求耗时不足 300ms,这里实际上已经因为 timerPromise 等待了 300ms,所以不需要额外等待
}

// 更新列表数据
list = await dataPromise;

// 关闭 loading 状态
loading = false;
}


在这个实现中,我们通过 Promise.all 来同时等待数据获取和 300ms 的定时器。这样无论请求时间多长,loading 状态都会至少保持 300ms。这种方式避免了使用单独的 setTimeout 来设置 loading 状态,减少了代码的复杂性并且更符合规范。
点赞
2026-03-23 09:06
心虹🍀
这个问题我之前也踩过坑,官方文档里其实没直接说最小展示时间这事,但社区里大家普遍用的方案是:记录开始时间,等数据回来后如果还没到 300ms,就再等一等。

核心就是别直接在请求 then 里把 loading 设成 false,先算下时间差,不够就再 setTimeout 补足。

举个简单例子(假设用的是 Vue):

data() {
return {
loading: false,
list: []
}
},
methods: {
fetchData() {
this.loading = true
const startTime = Date.now()

api.getList().then(res => {
this.list = res.data
const elapsed = Date.now() - startTime
const remain = 300 - elapsed
if (remain > 0) {
setTimeout(() => {
this.loading = false
}, remain)
} else {
this.loading = false
}
}).catch(err => {
this.loading = false
// 错误处理逻辑
})
}
}


这样不管请求快慢,loading 至少会显示 300ms,快的时候就多等会儿,慢的时候直接消失,不会卡顿。

另外提醒一句,别在请求失败时也强制等 300ms,用户点按钮出错还转圈,体验会更差——出错就该快点反馈。
点赞 3
2026-02-27 12:02