从零搭建Vue3.0组件之布局组件
一.Row、Col组件
import { computed, defineComponent, h } from "vue";
export default defineComponent({
name: 'ZRow',
props: {
tag: {
type: String,
default: 'div'
}
},
setup(props, { slots }) {
const classs = computed(() => [
'z-row'
])
return () => h(props.tag, {
class: classs.value
}, slots.default?.())
}
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { computed, defineComponent, h } from "vue"
export default defineComponent({
name: 'ZCol',
props: {
tag: {
type: String,
default: 'div',
}
},
setup(props, { slots }) {
const classs = computed(() => [
'z-col'
])
return () => h(props.tag, {
class: classs.value
}, slots.default?.())
}
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
二.设置列宽
row.scss
@import "common/var";
@import "mixins/mixins";
@include b(row){
display: flex;
flex-wrap: wrap;
}
1
2
3
4
5
6
2
3
4
5
6
col.scss
import { computed, defineComponent, h } from "vue"
export default defineComponent({
name: 'ZCol',
props: {
tag: {
type: String,
default: 'div'
},
span: {
type: Number,
default: 24
},
offset: {
type: Number,
default: 0,
}
},
setup(props, { slots }) {
const classs = computed(() => {
const ret: string[] = [];
const pos = ['span', 'offset'] as const;
pos.forEach(item => {
const size = props[item];
if (typeof size == 'number' && size > 0) {
ret.push(`z-col-${item}-${props[item]}`);
}
})
return [
'z-col',
...ret
]
})
return () => h(props.tag, {
class: classs.value
}, slots.default?.())
}
})
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
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
@import './common/var.scss';
@import './mixins/mixins.scss';
@for $i from 0 through 24 {
.#{$namespace}-col-span-#{$i} {
max-width: (1 / 24 * $i * 100) * 1%;
flex: (1/24 * $i * 100) * 1%;
}
.#{$namespace}-col-offset-#{$i} {
margin-left: (1 / 24 * $i * 100) * 1%;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
三.设置行信息
将Row组件中的gutter属性暴露出去,在Col组件中注入属性
provide('ZRow',props.gutter);
const style = computed(() => {
const ret = {
marginLeft: '',
marginRight: '',
}
if (props.gutter) { // 放大宽度
ret.marginLeft = `-${props.gutter / 2}px`
ret.marginRight = ret.marginLeft
}
return ret
})
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
setup(props, { slots }) {
const gutter = inject('ZRow', 0)
const style = computed(() => { // 设置间距
if (gutter) {
return {
paddingLeft: gutter / 2 + 'px',
paddingRight: gutter / 2 + 'px'
}
}
return {}
})
return () => h(props.tag, {
class: classs.value,
style: style.value
}, slots.default?.())
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[class*="#{$namespace}-col-"] {
box-sizing: border-box;
}
1
2
3
2
3
保证padding不影响宽度
四.响应式
$--sm: 768px !default;
$--md: 992px !default;
$--lg: 1200px !default;
$--xl: 1920px !default;
$--breakpoints: (
'xs' : (max-width: $--sm - 1),
'sm' : (min-width: $--sm),
'md' : (min-width: $--md),
'lg' : (min-width: $--lg),
'xl' : (min-width: $--xl)
);
@mixin res($key, $map: $--breakpoints) {
// 循环断点Map,如果存在则返回
@if map-has-key($map, $key) {
@media only screen and #{inspect(map-get($map, $key))} {
@content;
}
}
}
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
针对不同尺寸生成对应样式结构
@include res(xs) {
@for $i from 0 through 24 {
.#{$namespace}-col-xs-#{$i} {
max-width: (1 / 24 * $i * 100) * 1%;
flex: 0 0 (1 / 24 * $i * 100) * 1%;
}
.#{$namespace}-col-xs-offset-#{$i} {
margin-left: (1 / 24 * $i * 100) * 1%;
}
}
}
@include res(sm) {
@for $i from 0 through 24 {
.#{$namespace}-col-sm-#{$i} {
max-width: (1 / 24 * $i * 100) * 1%;
flex: 0 0 (1 / 24 * $i * 100) * 1%;
}
.#{$namespace}-col-sm-offset-#{$i} {
margin-left: (1 / 24 * $i * 100) * 1%;
}
}
}
@include res(md) {
@for $i from 0 through 24 {
.#{$namespace}-col-md-#{$i} {
max-width: (1 / 24 * $i * 100) * 1%;
flex: 0 0 (1 / 24 * $i * 100) * 1%;
}
.#{$namespace}-col-md-offset-#{$i} {
margin-left: (1 / 24 * $i * 100) * 1%;
}
}
}
@include res(lg) {
@for $i from 0 through 24 {
.#{$namespace}-col-lg-#{$i} {
max-width: (1 / 24 * $i * 100) * 1%;
flex: 0 0 (1 / 24 * $i * 100) * 1%;
}
.#{$namespace}-col-lg-offset-#{$i} {
margin-left: (1 / 24 * $i * 100) * 1%;
}
}
}
@include res(xl) {
@for $i from 0 through 24 {
.#{$namespace}-col-xl-#{$i} {
max-width: (1 / 24 * $i * 100) * 1%;
flex: 0 0 (1 / 24 * $i * 100) * 1%;
}
.#{$namespace}-col-xl-offset-#{$i} {
margin-left: (1 / 24 * $i * 100) * 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
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
col.ts
const sizes = ['xs', 'sm', 'md', 'lg', 'xl'] as const
sizes.forEach(size => {
if (typeof props[size] === 'number') {
ret.push(`z-col-${size}-${props[size]}`)
}
})
1
2
3
4
5
6
2
3
4
5
6
根据用户设置的属性
五.对其方式
row.ts
const classs = computed(() => [
'z-row',
props.justify !== 'start' ? `is-justify-${props.justify}` : '',
])
1
2
3
4
2
3
4
@include b(row) {
display: flex;
flex-wrap: wrap;
@include when(justify-center) {
justify-content: center;
}
@include when(justify-end) {
justify-content: flex-end;
}
@include when(justify-space-between) {
justify-content: space-between;
}
@include when(justify-space-around) {
justify-content: space-around;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
设置flex布局对其方式即可