Appearance
Button组件
一.定义组件所需Props
components/button/src/button.ts
import { ExtractPropTypes, PropType } from 'vue'
export type Size = 'tiny' | 'small' | 'medium' | 'large'
export type Type =
| 'primary'
| 'success'
| 'warning'
| 'danger'
| 'info'
| 'default'
| ''
export const buttonProps = {
size: String as PropType<Size>, // 按钮大小
type: {
type: String as PropType<Type>, // 按钮格式
validator: (val: string) => {
return [
'default',
'primary',
'success',
'warning',
'danger',
'info',
''
].includes(val)
},
default: ''
},
iconPlacement: {
// 图标位置
type: String as PropType<'left' | 'right'>,
default: 'left'
},
nativeType: {
// 按钮类型
type: String as PropType<'button' | 'submit' | 'reset'>,
default: 'button'
},
// 状态 加载、禁用、圆角
loading: Boolean,
disabled: Boolean,
round: Boolean
}
export const buttonEmits = {
click: (e: MouseEvent) => e instanceof MouseEvent
}
export type ButtonProps = ExtractPropTypes<typeof buttonProps>
export type buttonEmits = typeof buttonEmits
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
二.button.vue
结构实现
<template>
<button
:class="[
bem.b(),
bem.m(type),
bem.m(size),
bem.is('loading', loading),
bem.is('disabled', disabled),
bem.is('round', round)
]"
:disabled="disabled || loading"
:type="nativeType"
>
<slot></slot>
</button>
</template>
<script lang="ts" setup>
import { createNamespace } from '@zi-shui/utils/create'
import { buttonEmits, buttonProps } from './button'
defineOptions({
name: 'ZButton'
})
// 获取属性,及事件
const props = defineProps(buttonProps)
const emit = defineEmits(buttonEmits)
const bem = createNamespace('button')
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
三.Button入口编写
import { withInstall } from '@zi-shui/utils/withInstall'
import _Button from './src/button.vue'
const Button = withInstall(_Button)
export default Button // 导出Icon组件
export type { buttonProps } from './src/button'
declare module 'vue' {
export interface GlobalComponents {
ZButton: typeof Button
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
四.Button组件试用
<ZButton
:disabled="true"
:loading="true"
:round="true"
type="primary"
size="tiny"
>爱你😘</ZButton>
1
2
3
4
5
6
7
2
3
4
5
6
7
五.组件功能实现
1).样式编写
先准备点公共样式,放到theme-chalk/src/common/var.scss
$color-primary: #409eff;
$color-white: #ffffff;
$color-black: #000000;
$color-success: #67c23a;
$color-warning: #e6a23c;
$color-danger: #f56c6c;
$color-info: #909399;
1
2
3
4
5
6
7
2
3
4
5
6
7
@use 'mixins/mixins' as *;
@use 'common/var' as *;
@keyframes rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
@include b(button) {
// BEM规范
align-items: center;
display: inline-flex;
cursor: pointer;
outline: none;
border: #fafafa;
border-radius: 5px;
user-select: none;
min-height: 40px;
line-height: 1;
vertical-align: middle;
padding: 0 20px;
@include m(tiny) {
padding: 0 15px;
}
@include m(medium) {
padding: 0 20px;
}
@include m(small) {
padding: 0 18px;
}
@include m(large) {
padding: 0 25px;
}
@include when(disabled) {
// 针对不同类型处理
&,
&:hover,
&:focus {
cursor: not-allowed;
}
}
@include when(loading) {
// 针对不同类型处理
svg.loading {
animation: rotate 1s linear infinite;
}
}
@include when(round) {
border-radius: 20px;
}
@include m(primary) {
//渲染不同类型的button
@include button-variant($color-white, $color-primary, $color-primary);
}
@include m(success) {
@include button-variant($color-white, $color-success, $color-success);
}
@include m(warning) {
@include button-variant($color-white, $color-warning, $color-warning);
}
@include m(danger) {
@include button-variant($color-white, $color-danger, $color-danger);
}
@include m(info) {
@include button-variant($color-white, $color-info, $color-info);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
提供scss的辅助方法,方便后续使用
@mixin button-variant($color, $background-color, $border-color) {
color: $color;
background: $background-color;
border-color: $border-color;
}
1
2
3
4
5
2
3
4
5
2).插槽显示处理
编写个loading
组件用于显示loading
、loadingIcon.vue
<template>
<ZIcon>
<svg
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 1024 1024"
class="loading"
>
<path
d="M512 1024c-69.1 0-136.2-13.5-199.3-40.2C251.7 958 197 921 150 874c-47-47-84-101.7-109.8-162.7C13.5 648.2 0 581.1 0 512c0-19.9 16.1-36 36-36s36 16.1 36 36c0 59.4 11.6 117 34.6 171.3c22.2 52.4 53.9 99.5 94.3 139.9c40.4 40.4 87.5 72.2 139.9 94.3C395 940.4 452.6 952 512 952c59.4 0 117-11.6 171.3-34.6c52.4-22.2 99.5-53.9 139.9-94.3c40.4-40.4 72.2-87.5 94.3-139.9C940.4 629 952 571.4 952 512c0-59.4-11.6-117-34.6-171.3a440.45 440.45 0 0 0-94.3-139.9a437.71 437.71 0 0 0-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.2C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7c26.7 63.1 40.2 130.2 40.2 199.3s-13.5 136.2-40.2 199.3C958 772.3 921 827 874 874c-47 47-101.8 83.9-162.7 109.7c-63.1 26.8-130.2 40.3-199.3 40.3z"
fill="currentColor"
></path>
</svg>
</ZIcon>
</template>
<script lang="ts" setup>
import ZIcon from '@zi-shui/components/icon'
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
3).实现功能
<template>
<button
:class="[
bem.b(),
bem.m(type),
bem.m(size),
bem.is('loading', loading),
bem.is('disabled', disabled),
bem.is('round', round)
]"
:disabled="disabled || loading"
:type="nativeType"
@click="handleClick"
>
<template v-if="iconPlacement == 'left'">
<LoadingComponent v-if="loading"></LoadingComponent>
<template v-else-if="slots.icon">
<Component :is="slots.icon"></Component>
</template>
</template>
<slot></slot>
<template v-if="iconPlacement == 'right'">
<LoadingComponent v-if="loading"></LoadingComponent>
<template v-else-if="slots.icon">
<Component :is="slots.icon"></Component>
</template>
</template>
</button>
</template>
<script lang="ts" setup>
import { createNamespace } from '@zi-shui/utils/create'
import LoadingComponent from './loadingIcon.vue'
import { useSlots } from 'vue'
import { buttonEmits, buttonProps } from './button'
defineOptions({
name: 'ZButton'
})
// 获取属性,及事件
defineProps(buttonProps)
const emit = defineEmits(buttonEmits)
const bem = createNamespace('button')
const slots = useSlots()
const handleClick = (e: MouseEvent) => {
emit('click', e)
}
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
六.文档编写
# 按钮 Button
按钮用来触发一些操作。
## 基础用法
<script setup lang="ts">
import { BatteryDead,BatteryFullSharp,Heart } from '@vicons/ionicons5'
const handleClick = () =>{
alert('🙂')
}
</script>
<ZButton>Default</ZButton>
<ZButton type="primary">Primary</ZButton>
<ZButton type="success">Success</ZButton>
<ZButton type="warning">Warning</ZButton>
<ZButton type="danger">Danger</ZButton>
<ZButton type="info">Info</ZButton>
```vue
<template>
<ZButton>Default</ZButton>
<ZButton type="primary">Primary</ZButton>
<ZButton type="success">Success</ZButton>
<ZButton type="warning">Warning</ZButton>
<ZButton type="danger">Danger</ZButton>
<ZButton type="info">Info</ZButton>
</template>
```
## 禁用
<ZButton type="primary" disabled>Primary</ZButton>
```html
<ZButton type="primary" disabled>Primary</ZButton>
```
## 图标
<ZButton :round="true" size="large" @click="handleClick">
<template #icon>
<ZIcon size="20">
<Heart />
</ZIcon>
</template>
我爱你
</ZButton>
<ZButton :round="true" :loading="true">
<template #icon>
<ZIcon size="20">
<Heart />
</ZIcon>
</template>
我爱你
</ZButton>
<ZButton :round="true" icon-placement="right">
<template #icon>
<ZIcon size="20">
<Heart />
</ZIcon>
</template>
我爱你
</ZButton>
```html
<ZButton :round="true" size="large" @click="handleClick">
<template #icon>
<ZIcon size="20">
<Heart />
</ZIcon>
</template>
我爱你
</ZButton>
<ZButton :round="true" :loading="true">
<template #icon>
<ZIcon size="20">
<Heart />
</ZIcon>
</template>
我爱你
</ZButton>
<ZButton :round="true" icon-placement="right">
<template #icon>
<ZIcon size="20">
<Heart />
</ZIcon>
</template>
我爱你
</ZButton>
```
## 事件
<ZButton @click="handleClick">
点我啊
</ZButton>
```html
<ZButton @click="handleClick"> 点我啊 </ZButton>
```
## API
### Button Props
| 名称 | 类型 | 默认值 | 说明 |
| -------------- | ------------------------------------------------------ | ------- | -------------------- |
| size | tiny \| small \| medium \| large | medium | 按钮大小 |
| type | primary \| success \|warning \|danger \|info\| default | default | 按钮颜色 |
| icon-placement | left \| right | left | icon 位置 |
| nativeType | button \| reset \| submit | button | 按钮类型 |
| disabled | boolean | false | 按钮是否禁用 |
| loading | boolean | false | 按钮是否显示加载状态 |
| round | boolean | false | 按钮是否显示圆角 |
### Button Slots
| 名称 | 默认值 | 说明 |
| ------- | --------- | ---------- |
| default | undefined | 按钮的内容 |
| icon | undefined | 按钮的图标 |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128