Icon和Button组件
# Icon组件
使用
iconfont
添加图标 (opens new window)
根据iconfont官方引入symbol引用 (opens new window)
这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。与上面两种相比具有如下特点:
- 支持多色图标了,不再受单色限制。
- 通过一些技巧,支持像字体那样,通过
font-size
,color
来调整样式。 - 兼容性较差,支持 ie9+,及现代浏览器。
- 浏览器渲染svg的性能一般,还不如png。
# 代码
<template>
<svg class="r-icon" aria-hidden="true">
<use :xlink:href="`#icon-${icon}`" />
</svg>
</template>
<script>
import "./font";
export default {
props: {
icon: String,
},
name: "RIcon",
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
import Icon from './icon.vue'
import '../../style/icon.scss'
// Button组件是可以单独使用
// import {Button} from 'r-ui';
// app.use(Button)
Icon.install = (app) => { // Vue3.0 app createApp().use().mount()
app.component(Icon.name,Icon)
}
export default Icon
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 样式抽取
$namespace:'r-';
@mixin blockquote($block) {
$blockName: $namespace + $block !global;// r-xxx
.#{$blockName} {
@content;
}
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
@import "./common/var.scss";
@import "./mixins/mixins.scss";
@include blockquote(icon) {
width: 24px;
height: 24px;
vertical-align: middle;
}
1
2
3
4
5
6
7
2
3
4
5
6
7
# 效果
# Button组件
# 原理
- 控制loading和卡槽及位置处理;
- 样式内嵌,继承实现;blockquote;
# 实现功能规划
- [x] 按钮的基本用法
- [x] 按钮加载中状态
- [x] 图标按钮
- [x] 按钮组的实现
# 准备备用样式
├─common
│ |-- var.scss # 基本样式
└─mixins
│ |-- mixins.scss # 混合的方法
│ button.scss
| button-group.scss
| icon.scss
1
2
3
4
5
6
7
2
3
4
5
6
7
// 样式变量
$primary: #409EFF;
$success: #67C23A;
$warning: #E6A23C;
$danger: #F56C6C;
$info: #909399;
$primary-active: #3a8ee6;
$success-active: #5daf34;
$warning-active: #cf9236;
$danger-active: #dd6161;
$info-active: #82848a;
$font-size:12px;
$border-radius:4px;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
@import './common/_var.scss'; // 全局的样式
@import './mixins/mixins.scss'; // 方法
$color-list:(primary:$primary,
success:$success,
info:$info,
warning:$warning,
danger:$danger);
$color-active-list:(primary:$primary-active,
success:$success-active,
info:$info-active,
warning:$warning-active,
danger:$danger-active);
@include blockquote(button) {
@include status($color-list);
display: inline-flex;
font-size: $font-size;
border-radius: $border-radius;
padding: 0px 20px;
border: none;
outline: none;
min-width: 80px;
box-shadow: 2px 2px #ccc;
color: #fff;
align-items: center;
justify-content: center;
height: 40px;
line-height: 40px;
vertical-align: middle;
@keyframes rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.loading {
animation: rotate 1s linear infinite;
}
&:disabled {
cursor: not-allowed;
}
.icon {
fill: #fff;
vertical-align: middle;
}
&:active:not(:disabled) {
@include status($color-active-list);
}
&.r-button-left {
.icon {
order:1
}
span{
order:2
}
}
&.r-button-right {
.icon {
order:2
}
span{
order:1
}
}
}
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
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
# 按钮的实现
<template>
<button :class="classs" :disabled="loading">
<r-icon :icon="icon" v-if="icon && !loading" class="icon"></r-icon>
<r-icon icon="loading" v-if="loading" class="icon loading"></r-icon>
<span v-if="$slots.default">
<slot></slot>
</span>
</button>
</template>
<script>
import { computed } from "vue";
export default {
props: {
type: {
type: String,
default: "primary",
validator(type) {
if (
type &&
!["warning", "success", "danger", "info", "primary"].includes(type)
) {
console.log(
"组件的type类型必须为:" +
["warning", "success", "danger", "info", "primary"].join("、")
);
}
return true;
},
},
icon: String,
loading:{
type:Boolean,
default:false
},
position:{
type:String,
default:'left'
}
},
name: "RButton",
setup(props, context) {
// 计算出所有样式
const classs = computed(() => [
`r-button`,
`r-button-${props.type}`,
`r-button-${props.position}`
]);
return {
classs,
};
},
};
</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
49
50
51
52
53
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
# ButtonGroup组件
# 原理
- 做内容上的左右及边框样式处理;
- 主要还是拿到实例节点下的孩子判断是否是Buton验证;
# 逻辑
以按钮组的方式出现,常用于多项类似操作。主要还是拿到实例节点下的孩子判断是否是Buton验证;
<template>
<div class="r-button-group">
<slot></slot>
</div>
</template>
<script>
import { onMounted, getCurrentInstance } from "vue";
export default {
name: "RButtonGroup",
setup(props) {
onMounted(() => {
let context = getCurrentInstance();
let ele = context.ctx.$el;
let children = ele.children;
for (let i = 0; i < children.length; i++) {
console.assert(children[i].tagName === "BUTTON", "必须子节点是button");
}
});
},
};
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 样式
处理左右两边及中间样式;
@import "./common/var.scss"; // 公共样式
@import "./mixins/mixins.scss";
@include blockquote(button-group) {
display: inline-flex;
vertical-align: middle;
button {
border-radius: 0;
position: relative;
box-shadow: none;
&:not(first-child) {
margin-left: -1px;
}
&:first-child {
border-top-left-radius: $border-radius;
border-bottom-left-radius: $border-radius;
}
&:last-child {
border-top-right-radius: $border-radius;
border-bottom-right-radius: $border-radius;
}
}
button:hover {
z-index: 1;
}
button:focus {
z-index: 2;
}
}
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
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
#
上次更新: 2022/04/15, 05:41:28