mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-25 02:41:46 +08:00
feat: loading component
This commit is contained in:
parent
e671e22ea5
commit
e0f9382123
60
src-next/loading/README.md
Normal file
60
src-next/loading/README.md
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
# Loading
|
||||||
|
|
||||||
|
### Install
|
||||||
|
|
||||||
|
```js
|
||||||
|
import Vue from 'vue';
|
||||||
|
import { Loading } from 'vant';
|
||||||
|
|
||||||
|
Vue.use(Loading);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Type
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-loading /> <van-loading type="spinner" />
|
||||||
|
```
|
||||||
|
|
||||||
|
### Color
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-loading color="#1989fa" /> <van-loading type="spinner" color="#1989fa" />
|
||||||
|
```
|
||||||
|
|
||||||
|
### Size
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-loading size="24" /> <van-loading type="spinner" size="24px" />
|
||||||
|
```
|
||||||
|
|
||||||
|
### Text
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-loading size="24px">Loading...</van-loading>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Vertical
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-loading size="24px" vertical>Loading...</van-loading>
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
### Props
|
||||||
|
|
||||||
|
| Attribute | Description | Type | Default |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| color | Loading color | _string_ | `#c9c9c9` |
|
||||||
|
| type | Can be set to `spinner` | _string_ | `circular` |
|
||||||
|
| size | Icon size | _number \| string_ | `30px` |
|
||||||
|
| text-size | Text font size | _number \| string_ | `14px` |
|
||||||
|
| vertical | Whether to arrange icons and text content vertically | _boolean_ | `false` |
|
||||||
|
|
||||||
|
### Slots
|
||||||
|
|
||||||
|
| Name | Description |
|
||||||
|
| ------- | ------------ |
|
||||||
|
| default | Loading text |
|
70
src-next/loading/README.zh-CN.md
Normal file
70
src-next/loading/README.zh-CN.md
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
# Loading 加载
|
||||||
|
|
||||||
|
### 引入
|
||||||
|
|
||||||
|
```js
|
||||||
|
import Vue from 'vue';
|
||||||
|
import { Loading } from 'vant';
|
||||||
|
|
||||||
|
Vue.use(Loading);
|
||||||
|
```
|
||||||
|
|
||||||
|
## 代码演示
|
||||||
|
|
||||||
|
### 加载类型
|
||||||
|
|
||||||
|
通过`type`属性可以设置加载图标的类型,默认为`circular`,可选值为`spinner`
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-loading /> <van-loading type="spinner" />
|
||||||
|
```
|
||||||
|
|
||||||
|
### 自定义颜色
|
||||||
|
|
||||||
|
通过`color`属性设置加载图标的颜色
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-loading color="#1989fa" /> <van-loading type="spinner" color="#1989fa" />
|
||||||
|
```
|
||||||
|
|
||||||
|
### 自定义大小
|
||||||
|
|
||||||
|
通过`size`属性设置加载图标的大小,默认单位为`px`
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-loading size="24" /> <van-loading type="spinner" size="24px" />
|
||||||
|
```
|
||||||
|
|
||||||
|
### 加载文案
|
||||||
|
|
||||||
|
可以使用默认插槽在图标的右侧插入加载文案
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-loading size="24px">加载中...</van-loading>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 垂直排列
|
||||||
|
|
||||||
|
设置`vertical`属性后,图标和文案会垂直排列
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-loading size="24px" vertical>加载中...</van-loading>
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
### Props
|
||||||
|
|
||||||
|
| 参数 | 说明 | 类型 | 默认值 |
|
||||||
|
| --------- | ---------------------------- | ------------------ | ---------- |
|
||||||
|
| color | 颜色 | _string_ | `#c9c9c9` |
|
||||||
|
| type | 类型,可选值为 `spinner` | _string_ | `circular` |
|
||||||
|
| size | 加载图标大小,默认单位为`px` | _number \| string_ | `30px` |
|
||||||
|
| text-size | 文字大小,默认单位为`px` | _number \| string_ | `14px` |
|
||||||
|
| vertical | 是否垂直排列图标和文字内容 | _boolean_ | `false` |
|
||||||
|
|
||||||
|
### Slots
|
||||||
|
|
||||||
|
| 名称 | 说明 |
|
||||||
|
| ------- | -------- |
|
||||||
|
| default | 加载文案 |
|
68
src-next/loading/demo/index.vue
Normal file
68
src-next/loading/demo/index.vue
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
<template>
|
||||||
|
<demo-section>
|
||||||
|
<demo-block :title="t('type')">
|
||||||
|
<van-loading />
|
||||||
|
<van-loading type="spinner" />
|
||||||
|
</demo-block>
|
||||||
|
|
||||||
|
<demo-block :title="t('color')">
|
||||||
|
<van-loading color="#1989fa" />
|
||||||
|
<van-loading type="spinner" color="#1989fa" />
|
||||||
|
</demo-block>
|
||||||
|
|
||||||
|
<demo-block :title="t('size')">
|
||||||
|
<van-loading size="24" />
|
||||||
|
<van-loading type="spinner" size="24" />
|
||||||
|
</demo-block>
|
||||||
|
|
||||||
|
<demo-block :title="t('text')">
|
||||||
|
<van-loading size="24px">
|
||||||
|
{{ t('loading') }}
|
||||||
|
</van-loading>
|
||||||
|
</demo-block>
|
||||||
|
|
||||||
|
<demo-block :title="t('vertical')">
|
||||||
|
<van-loading size="24px" vertical>
|
||||||
|
{{ t('loading') }}
|
||||||
|
</van-loading>
|
||||||
|
</demo-block>
|
||||||
|
</demo-section>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
i18n: {
|
||||||
|
'zh-CN': {
|
||||||
|
type: '加载类型',
|
||||||
|
text: '加载文案',
|
||||||
|
size: '自定义大小',
|
||||||
|
color: '自定义颜色',
|
||||||
|
vertical: '垂直排列',
|
||||||
|
},
|
||||||
|
'en-US': {
|
||||||
|
type: 'Type',
|
||||||
|
text: 'Text',
|
||||||
|
size: 'Size',
|
||||||
|
color: 'Color',
|
||||||
|
vertical: 'Vertical',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
@import '../../style/var';
|
||||||
|
|
||||||
|
.demo-loading {
|
||||||
|
background: @white;
|
||||||
|
|
||||||
|
.van-loading {
|
||||||
|
display: inline-block;
|
||||||
|
margin: 5px 0 5px 20px;
|
||||||
|
|
||||||
|
&--vertical {
|
||||||
|
display: inline-flex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
64
src-next/loading/index.js
Normal file
64
src-next/loading/index.js
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
// Utils
|
||||||
|
import { createNamespace, addUnit } from '../utils';
|
||||||
|
|
||||||
|
const [createComponent, bem] = createNamespace('loading');
|
||||||
|
|
||||||
|
const SpinIcon = [];
|
||||||
|
for (let i = 0; i < 12; i++) {
|
||||||
|
SpinIcon.push(<i />);
|
||||||
|
}
|
||||||
|
|
||||||
|
const CircularIcon = (
|
||||||
|
<svg class={bem('circular')} viewBox="25 25 50 50">
|
||||||
|
<circle cx="50" cy="50" r="20" fill="none" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default createComponent({
|
||||||
|
props: {
|
||||||
|
color: String,
|
||||||
|
size: [Number, String],
|
||||||
|
vertical: Boolean,
|
||||||
|
textSize: [Number, String],
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
default: 'circular',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
genLoadingText() {
|
||||||
|
if (this.$slots.default) {
|
||||||
|
const style = this.textSize && {
|
||||||
|
fontSize: addUnit(this.textSize),
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span class={bem('text')} style={style}>
|
||||||
|
{this.$slots.default()}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { color, size, type, vertical } = this;
|
||||||
|
|
||||||
|
const style = { color };
|
||||||
|
if (size) {
|
||||||
|
const iconSize = addUnit(size);
|
||||||
|
style.width = iconSize;
|
||||||
|
style.height = iconSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div class={bem([type, { vertical }])}>
|
||||||
|
<span class={bem('spinner', type)} style={style}>
|
||||||
|
{type === 'spinner' ? SpinIcon : CircularIcon}
|
||||||
|
</span>
|
||||||
|
{this.genLoadingText()}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
103
src-next/loading/index.less
Normal file
103
src-next/loading/index.less
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
@import '../style/var';
|
||||||
|
|
||||||
|
.van-loading {
|
||||||
|
position: relative;
|
||||||
|
color: @loading-spinner-color;
|
||||||
|
font-size: 0;
|
||||||
|
vertical-align: middle;
|
||||||
|
|
||||||
|
&__spinner {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
width: @loading-spinner-size;
|
||||||
|
// compatible for 1.x, users may set width or height in root element
|
||||||
|
max-width: 100%;
|
||||||
|
height: @loading-spinner-size;
|
||||||
|
max-height: 100%;
|
||||||
|
vertical-align: middle;
|
||||||
|
animation: van-rotate @loading-spinner-animation-duration linear infinite;
|
||||||
|
|
||||||
|
&--spinner {
|
||||||
|
animation-timing-function: steps(12);
|
||||||
|
|
||||||
|
i {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
display: block;
|
||||||
|
width: 2px;
|
||||||
|
height: 25%;
|
||||||
|
margin: 0 auto;
|
||||||
|
background-color: currentColor;
|
||||||
|
border-radius: 40%;
|
||||||
|
content: ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&--circular {
|
||||||
|
animation-duration: 2s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__circular {
|
||||||
|
display: block;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
circle {
|
||||||
|
animation: van-circular 1.5s ease-in-out infinite;
|
||||||
|
stroke: currentColor;
|
||||||
|
stroke-width: 3;
|
||||||
|
stroke-linecap: round;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__text {
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: @padding-xs;
|
||||||
|
color: @loading-text-color;
|
||||||
|
font-size: @loading-text-font-size;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--vertical {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.van-loading__text {
|
||||||
|
margin: @padding-xs 0 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes van-circular {
|
||||||
|
0% {
|
||||||
|
stroke-dasharray: 1, 200;
|
||||||
|
stroke-dashoffset: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
stroke-dasharray: 90, 150;
|
||||||
|
stroke-dashoffset: -40;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
stroke-dasharray: 90, 150;
|
||||||
|
stroke-dashoffset: -120;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.generate-spinner(@n, @i: 1) when (@i =< @n) {
|
||||||
|
.van-loading__spinner--spinner i:nth-of-type(@{i}) {
|
||||||
|
transform: rotate(@i * 30deg);
|
||||||
|
opacity: 1 - (0.75 / 12) * (@i - 1);
|
||||||
|
}
|
||||||
|
.generate-spinner(@n, (@i + 1));
|
||||||
|
}
|
||||||
|
.generate-spinner(12);
|
28
src-next/loading/test/__snapshots__/demo.spec.js.snap
Normal file
28
src-next/loading/test/__snapshots__/demo.spec.js.snap
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`renders demo correctly 1`] = `
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<div class="van-loading van-loading--circular"><span class="van-loading__spinner van-loading__spinner--circular"><svg viewBox="25 25 50 50" class="van-loading__circular"><circle cx="50" cy="50" r="20" fill="none"></circle></svg></span></div>
|
||||||
|
<div class="van-loading van-loading--spinner"><span class="van-loading__spinner van-loading__spinner--spinner"><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i></span></div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="van-loading van-loading--circular"><span class="van-loading__spinner van-loading__spinner--circular" style="color: rgb(25, 137, 250);"><svg viewBox="25 25 50 50" class="van-loading__circular"><circle cx="50" cy="50" r="20" fill="none"></circle></svg></span></div>
|
||||||
|
<div class="van-loading van-loading--spinner"><span class="van-loading__spinner van-loading__spinner--spinner" style="color: rgb(25, 137, 250);"><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i></span></div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="van-loading van-loading--circular"><span class="van-loading__spinner van-loading__spinner--circular" style="width: 24px; height: 24px;"><svg viewBox="25 25 50 50" class="van-loading__circular"><circle cx="50" cy="50" r="20" fill="none"></circle></svg></span></div>
|
||||||
|
<div class="van-loading van-loading--spinner"><span class="van-loading__spinner van-loading__spinner--spinner" style="width: 24px; height: 24px;"><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i></span></div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="van-loading van-loading--circular"><span class="van-loading__spinner van-loading__spinner--circular" style="width: 24px; height: 24px;"><svg viewBox="25 25 50 50" class="van-loading__circular"><circle cx="50" cy="50" r="20" fill="none"></circle></svg></span><span class="van-loading__text">
|
||||||
|
加载中...
|
||||||
|
</span></div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="van-loading van-loading--circular van-loading--vertical"><span class="van-loading__spinner van-loading__spinner--circular" style="width: 24px; height: 24px;"><svg viewBox="25 25 50 50" class="van-loading__circular"><circle cx="50" cy="50" r="20" fill="none"></circle></svg></span><span class="van-loading__text">
|
||||||
|
加载中...
|
||||||
|
</span></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
5
src-next/loading/test/__snapshots__/index.spec.js.snap
Normal file
5
src-next/loading/test/__snapshots__/index.spec.js.snap
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`size prop 1`] = `<div class="van-loading van-loading--circular"><span class="van-loading__spinner van-loading__spinner--circular" style="width: 20px; height: 20px;"><svg viewBox="25 25 50 50" class="van-loading__circular"><circle cx="50" cy="50" r="20" fill="none"></circle></svg></span></div>`;
|
||||||
|
|
||||||
|
exports[`text-size prop 1`] = `<div class="van-loading van-loading--circular"><span class="van-loading__spinner van-loading__spinner--circular"><svg viewBox="25 25 50 50" class="van-loading__circular"><circle cx="50" cy="50" r="20" fill="none"></circle></svg></span><span class="van-loading__text" style="font-size: 20px;">Text</span></div>`;
|
4
src-next/loading/test/demo.spec.js
Normal file
4
src-next/loading/test/demo.spec.js
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import Demo from '../demo';
|
||||||
|
import { snapshotDemo } from '../../../test/demo';
|
||||||
|
|
||||||
|
snapshotDemo(Demo);
|
25
src-next/loading/test/index.spec.js
Normal file
25
src-next/loading/test/index.spec.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { mount } from '../../../test';
|
||||||
|
import Loading from '..';
|
||||||
|
|
||||||
|
test('size prop', () => {
|
||||||
|
const wrapper = mount(Loading, {
|
||||||
|
propsData: {
|
||||||
|
size: 20,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(wrapper).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('text-size prop', () => {
|
||||||
|
const wrapper = mount(Loading, {
|
||||||
|
propsData: {
|
||||||
|
textSize: 20,
|
||||||
|
},
|
||||||
|
scopedSlots: {
|
||||||
|
default: () => 'Text',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(wrapper).toMatchSnapshot();
|
||||||
|
});
|
@ -192,10 +192,10 @@ module.exports = {
|
|||||||
// path: 'dropdown-menu',
|
// path: 'dropdown-menu',
|
||||||
// title: 'DropdownMenu 下拉菜单',
|
// title: 'DropdownMenu 下拉菜单',
|
||||||
// },
|
// },
|
||||||
// {
|
{
|
||||||
// path: 'loading',
|
path: 'loading',
|
||||||
// title: 'Loading 加载',
|
title: 'Loading 加载',
|
||||||
// },
|
},
|
||||||
// {
|
// {
|
||||||
// path: 'notify',
|
// path: 'notify',
|
||||||
// title: 'Notify 消息通知',
|
// title: 'Notify 消息通知',
|
||||||
@ -543,10 +543,10 @@ module.exports = {
|
|||||||
// path: 'dropdown-menu',
|
// path: 'dropdown-menu',
|
||||||
// title: 'DropdownMenu',
|
// title: 'DropdownMenu',
|
||||||
// },
|
// },
|
||||||
// {
|
{
|
||||||
// path: 'loading',
|
path: 'loading',
|
||||||
// title: 'Loading',
|
title: 'Loading',
|
||||||
// },
|
},
|
||||||
// {
|
// {
|
||||||
// path: 'notify',
|
// path: 'notify',
|
||||||
// title: 'Notify',
|
// title: 'Notify',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user