Spin
是一个载入状态元件,当页面正在处理非同步行为,或需要让用户等待的作业时,用来显示以缓解用户等待的焦虑。
一个简单的 loading 状态,只需要拿一个适合的 icon 来旋转就可以了
Spin 元件虽然相对单纯,但是也是有一些做法可以让我们使用起来更为方便。
内容加载中
Antd 让 Spin 也能够拥有 children 元件,这样的做法可以让载入的同时也能够看到内容。
<Spin spinning={this.state.spinning}>
{children}
</Spin>
假设一个情境是我们需要编辑某个资料 table 或是留言板,每做一个小动作就要打一次 API ,每次打 API 就会整页白掉变成 loading 状态,载入完之後再重新显示资料,如果这些操作很频繁的话,那这样的使用者体验必定很不好。
因此若这一页的内容正在载入中,但是又不想要整个区块换成载入状态,或许用这种内容加载的方式也是一种选择。
组建大小
透过一个 props 来决定 Spin 的大小,也是很基本却很重要的性质之一,毕竟把 Spin 放在一颗按钮里面,跟把 Spin 放在整个页面的中间,所需要的 size 很可能会不同。Antd 这边只提供可选的选项,分别是 small
, default
, large
。
indicator
随着网站的不同,为了配合设计师的设计,我们也需要能够随心所欲的更改 Spin 的 icon。当然一个网站应该不太会设计成每一页的 Spin 都长不一样,不过 Antd 是为了让广大的开发者能够使用,因此会有这个需求,如果是自己的网站要使用,应该一到两种应该就很够用了。
属性 | 说明 | 类型 | 默认值 |
---|---|---|---|
className | 客制化样式 | string | |
isLoading | 是否载入中 | boolean | false |
indicator | 自定义载入符号 | ReactNode , string |
<CircularProgress /> |
children | 内容 | ReactNode , string |
Spin
最简单的原理就是根据 是否加载中
这个 boolean 来判断是否要显示载入符号,其他的部分就是根据不同情境来调整样式。
那今天我们要实作的情境有两种,一种是 Spin 直接当作加载元件,一种是 Spin 会成为一个加载容器,所以我的想法如下:
const Spin = ({
indicator, isLoading, children, ...props
}) => {
if (!children) {
return indicator;
}
return (
<SpinContainer {...props}>
{children}
{isLoading && indicator}
</SpinContainer>
);
};
主要核心的想法到目前为止就已经差不多了,其他的部分就是样式上的调整。
当我们要直接 show 出一个 Spin:
<Spin />
我预设的样式就会是这样:
Custom Indicator
当然这个样式我偷懒是直接拿 MUI 的 <CircularProgress />
来使用。
如果我们要客制化样式也是可以的,假设我们今天拿到一个 SVG 档,我把它转换成 JS:
export const SpinnerIcon = (props) => (
<svg
aria-hidden="true"
focusable="false"
data-prefix="fas"
data-icon="spinner"
role="img"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 512 512"
className="svg-inline--fa fa-spinner fa-w-16 fa-3x"
{...props}
>
<path fill="currentColor" d="M304 48c0 ...." className="" />
</svg>
);
然後我就能够自己做一个 indicator,当作 props 传入,或是直接做进 Spin
元件当作预设的 indicator,我这边以 props 传入为例:
import styled, { keyframes } from 'styled-components';
const rotateAnimation = keyframes`
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
`;
const RotateContainer = styled.div`
width: 40px;
height: 40px;
animation: ${rotateAnimation} 1000ms ease-in-out infinite;
`;
<Spin
indicator={(
<RotateContainer>
<FaSpinner />
</RotateContainer>
)}
/>
就会是这样:
Spin As Container
再来就是我们把 Spin
当作一个容器,让他的 children 有载入状态,使用起来如下:
<Spin isLoading>
<Content />
</Spin>
我的作法提供给大家参考:
<SpinContainer {...props}>
{children}
{isLoading && (
<>
<Mask />
<Indicator
ref={indicatorRef}
className="spin__indicator"
$indicatorSize={indicatorSize}
>
{indicator}
</Indicator>
</>
)}
</SpinContainer>
主要的想法就是 <SpinContainer />
这一层设为 position: relative;
,然後里面的 <Indicator />
设为 position: absolute;
让他能够盖在内容上面,并做置中的定位。
然後可以看到我这边多给一个 <Mask />
元件,主要是如果直接 show 出 indicator 叠在内容上的话,会显得有点缭乱,所以我想要弱化载入中时内容的显眼度,来凸显加载中的样式,以下就是今天的成果展示:
Spin 元件原始码:
Source code
Storybook:
Spin
Hi Dai Gei Ho~ 我是Winnie~ 今天是第八天,中秋连假到数结束第二天~ 在开始说明...
终於进入小车实作啦~~~~上个连假笔者本来就要来写的,结果拖到这个连假才有空来玩车车XD 首先介绍笔...
今天要来实作的快速排序法Quick Sort,虽然不是最佳的(以前学习的时候看到他的名字以为它会是最...
上一篇先介绍运用的知识点,这篇会着重在实作时的心路历程...不是啦,是怎麽把这个网页写出来的。先上成...
参阅: https://codertw.com/%E5%89%8D%E7%AB%AF%E9%96%8...