在前端开发的世界里,用户体验(UX)是永远无法被忽视的一个方面,尤其是在web应用中,加载时的流畅度、响应性直接决定了用户是否愿意继续使用你的应用。今天,想和大家分享一个在iOS系统设置中使用的加载小技巧——延迟显示加载动画,这个技巧可以让你的页面加载更加平滑,避免因为请求过快而给用户带来不好的页面闪烁体验。
背景
在日常的开发中,常见的做法是在发起网络请求时,通常会显示一个 loading 动画,表示数据正在加载中。但问题在于,假如数据加载非常快(比如几毫秒),那么整个页面可能会突然闪烁了一下,让用户感到困惑。而咱们又不能直接去除该 loding 动画,否则在慢速请求的情况,用户会以为页面没有反应。
实现思路
如何解决这个问题呢?ios的系统设置中给出的答案是:延迟显示加载动画。那么咱们就来简单的实现一下该功能吧。
核心思路
- 如果请求时间非常短(比如小于 200ms),我们不显示 loading 动画。
- 如果请求时间较长(超过 200ms),我们才显示 loading 动画。而在显示 loading 动画后,需要计算请求的时长,确保 loading 会显示500ms才消失(确保不会有瞬间闪烁的问题)
简单来说,如果数据响应的速度非常快,我们认为用户几乎没有等待时间,不需要显示 loading;如果请求时间较长,那么我们就需要给用户一个正在加载的提示,并且这个加载的动画需要显示一定的时长,避免让他们觉得应用卡顿无响应或者出现闪烁之类的不好体验。
时间选择
200ms 和 500ms这 两个时间值并非严格的标准,而是根据用户的视觉感知和交互体验来设置的。一般来说,200ms 是用户能够感知到交互延迟的一个临界点,而 500ms是用户感觉到是否有闪烁的临界点,这个值也可以根据具体需求进行调整,但 200ms 和 500ms作为一个基准值,能够满足大多数场景下的需求。
效果对比
可以发现,延迟显示加载动画在低延迟时,不会有明显的loading或者闪烁的问题
而在高延迟的场景下,延迟加载动画的执行速度会稍慢一些(200ms后才显示),但也基本是在用户的无感知的情况下。
代码
import React, { useState, useEffect } from 'react';
import { Button, Spin, Select } from 'antd';
import "./index.less"
const DEFAULT_DURATION = 200;
const DEFAULT_LOADING_SHOW_TIME = 500;
export default function IosLoading() {
const [isLoading, setIsLoading] = useState(false);
const [duration, setDuration] = useState(50);
const [data, setData] = useState(null);
const mockRequest = () => {
const start = Date.now();
return new Promise((resolve) => {
setTimeout(
() =>
resolve({
code: 200,
message: 'success',
duration: Date.now() - start,
}),
duration,
);
});
};
// 请求
const fetchData = async () => {
const start = Date.now();
setData(null);
// 在请求开始后xxx ms开始显示 loading
const loadingTimer = setTimeout(() => {
setIsLoading(true);
}, DEFAULT_DURATION);
mockRequest().then((res) => {
const end = Date.now();
const _duration = end - start;
if (_duration < DEFAULT_DURATION) {
clearTimeout(loadingTimer);
setIsLoading(false);
setData(res);
} else {
setTimeout(() => {
setData(res);
setIsLoading(false);
}, DEFAULT_LOADING_SHOW_TIME + DEFAULT_DURATION - _duration);
}
});
};
const defaultfetchData = async () => {
setIsLoading(true);
mockRequest().then((res) => {
setIsLoading(false);
setData(res);
});
}
return (
<div className='ios-loading'>
<div>
<Select
style={{ marginBottom: 12, width: 120 }}
value={duration}
onChange={(value) => {
setDuration(value);
}}
options={[
{ label: '50ms', value: 50 },
{ label: '100ms', value: 100 },
{ label: '150ms', value: 150 },
{ label: '200ms', value: 200 },
{ label: '500ms', value: 500 },
{ label: '1000ms', value: 1000 },
]}
/>
</div>
<div>
<Button type='primary' onClick={fetchData}>
延时动画请求
</Button>
<Button onClick={defaultfetchData}>
默认请求
</Button>
</div>
{isLoading && <div className='loading'><Spin size='large' /></div>}
<div>请求耗时:{data?.duration}ms</div>
</div>
);
}
源码和 demo 链接
github:github.com/sulgweb/dem…
demo 链接:demo.sulg.top/
小结
尽管我们常常会默认展示 loading 动画,但其实这并不是唯一的选择。在某些情况下,通过延迟显示加载动画能够大大提升用户体验,避免了因网络请求快速导致的不必要的加载展示。通过这种方式,我们让加载动画成为真正需要时才出现的用户友好提示,而不是一个“冗余”的存在。
希望这个小技巧能帮助你提升应用的加载体验,减少因加载过快给用户带来不好的体验。毕竟,良好的用户体验往往是在细节处做得好,才会让用户无感知地享受到应用的流畅与高效。