mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-05-22 06:31:45 +08:00
feat(Row): gutter support vertical space (#12439)
Co-authored-by: inottn <inottn@outlook.com>
This commit is contained in:
parent
a75a458062
commit
632ff0be31
@ -4,6 +4,7 @@ import {
|
|||||||
createNamespace,
|
createNamespace,
|
||||||
makeNumericProp,
|
makeNumericProp,
|
||||||
makeStringProp,
|
makeStringProp,
|
||||||
|
extend,
|
||||||
} from '../utils';
|
} from '../utils';
|
||||||
import { useParent } from '@vant/use';
|
import { useParent } from '@vant/use';
|
||||||
import { ROW_KEY } from '../row/Row';
|
import { ROW_KEY } from '../row/Row';
|
||||||
@ -31,15 +32,21 @@ export default defineComponent({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { spaces } = parent;
|
const { spaces, verticalSpaces } = parent;
|
||||||
|
let styles = {};
|
||||||
if (spaces && spaces.value && spaces.value[index.value]) {
|
if (spaces && spaces.value && spaces.value[index.value]) {
|
||||||
const { left, right } = spaces.value[index.value];
|
const { left, right } = spaces.value[index.value];
|
||||||
return {
|
styles = {
|
||||||
paddingLeft: left ? `${left}px` : null,
|
paddingLeft: left ? `${left}px` : null,
|
||||||
paddingRight: right ? `${right}px` : null,
|
paddingRight: right ? `${right}px` : null,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { bottom } = verticalSpaces.value[index.value] || {};
|
||||||
|
|
||||||
|
return extend(styles, {
|
||||||
|
marginBottom: bottom ? `${bottom}px` : null,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
|
@ -53,6 +53,20 @@ Set grid spacing using `gutter` attribute. The default value is 0.
|
|||||||
</van-row>
|
</van-row>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Vertical Spacing
|
||||||
|
|
||||||
|
If you want to set the vertical spacing, you can set `[horizontal, vertical]` as an array.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!-- set the vertical spacing -->
|
||||||
|
<van-row :gutter="[20, 20]">
|
||||||
|
<van-col span="12">span: 12</van-col>
|
||||||
|
<van-col span="12">span: 12</van-col>
|
||||||
|
<van-col span="12">span: 12</van-col>
|
||||||
|
<van-col span="12">span: 12</van-col>
|
||||||
|
</van-row>
|
||||||
|
```
|
||||||
|
|
||||||
### Justify Content
|
### Justify Content
|
||||||
|
|
||||||
```html
|
```html
|
||||||
@ -87,7 +101,7 @@ Set grid spacing using `gutter` attribute. The default value is 0.
|
|||||||
|
|
||||||
| Attribute | Description | Type | Default |
|
| Attribute | Description | Type | Default |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| gutter | Grid spacing(px) | _number \| string_ | - |
|
| gutter | Grid spacing(px) | _number \| string \| Array_ | - |
|
||||||
| tag | Custom element tag | _string_ | `div` |
|
| tag | Custom element tag | _string_ | `div` |
|
||||||
| justify | Flex main axis, can be set to end/center/space-around/space-between | _string_ | `start` |
|
| justify | Flex main axis, can be set to end/center/space-around/space-between | _string_ | `start` |
|
||||||
| align | Flex cross axis, be set to center/bottom | _string_ | `top` |
|
| align | Flex cross axis, be set to center/bottom | _string_ | `top` |
|
||||||
|
@ -52,6 +52,20 @@ Layout 组件提供了 `24列栅格`,通过在 `Col` 上添加 `span` 属性
|
|||||||
</van-row>
|
</van-row>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 垂直间距
|
||||||
|
|
||||||
|
如果需要设置垂直间距,可以使用数组形式设置 `[水平间距, 垂直间距]`。
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!-- 设置垂直间距 -->
|
||||||
|
<van-row :gutter="[20, 20]">
|
||||||
|
<van-col span="12">span: 12</van-col>
|
||||||
|
<van-col span="12">span: 12</van-col>
|
||||||
|
<van-col span="12">span: 12</van-col>
|
||||||
|
<van-col span="12">span: 12</van-col>
|
||||||
|
</van-row>
|
||||||
|
```
|
||||||
|
|
||||||
### 对齐方式
|
### 对齐方式
|
||||||
|
|
||||||
通过 `justify` 属性可以设置主轴上内容的对齐方式,等价于 flex 布局中的 `justify-content` 属性。
|
通过 `justify` 属性可以设置主轴上内容的对齐方式,等价于 flex 布局中的 `justify-content` 属性。
|
||||||
@ -92,7 +106,7 @@ Layout 组件提供了 `24列栅格`,通过在 `Col` 上添加 `span` 属性
|
|||||||
|
|
||||||
| 参数 | 说明 | 类型 | 默认值 |
|
| 参数 | 说明 | 类型 | 默认值 |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| gutter | 列元素之间的间距(单位为 px) | _number \| string_ | - |
|
| gutter | 列元素之间的间距(单位为 px) | _number \| string \| Array_ | - |
|
||||||
| tag | 自定义元素标签 | _string_ | `div` |
|
| tag | 自定义元素标签 | _string_ | `div` |
|
||||||
| justify | 主轴对齐方式,可选值为 `end` `center` <br> `space-around` `space-between` | _string_ | `start` |
|
| justify | 主轴对齐方式,可选值为 `end` `center` <br> `space-around` `space-between` | _string_ | `start` |
|
||||||
| align | 交叉轴对齐方式,可选值为 `center` `bottom` | _string_ | `top` |
|
| align | 交叉轴对齐方式,可选值为 `center` `bottom` | _string_ | `top` |
|
||||||
|
@ -7,10 +7,12 @@ const t = useTranslate({
|
|||||||
'zh-CN': {
|
'zh-CN': {
|
||||||
title2: '在列元素之间增加间距',
|
title2: '在列元素之间增加间距',
|
||||||
justify: '对齐方式',
|
justify: '对齐方式',
|
||||||
|
vertical: '垂直间距',
|
||||||
},
|
},
|
||||||
'en-US': {
|
'en-US': {
|
||||||
title2: 'Column Spacing',
|
title2: 'Column Spacing',
|
||||||
justify: 'Justify Content',
|
justify: 'Justify Content',
|
||||||
|
vertical: 'Vertical Spacing',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@ -41,6 +43,17 @@ const t = useTranslate({
|
|||||||
</van-row>
|
</van-row>
|
||||||
</demo-block>
|
</demo-block>
|
||||||
|
|
||||||
|
<demo-block :title="t('vertical')">
|
||||||
|
<div class="demo-vertical-space">
|
||||||
|
<van-row :gutter="[20, 20]">
|
||||||
|
<van-col span="12">span: 12</van-col>
|
||||||
|
<van-col span="12">span: 12</van-col>
|
||||||
|
<van-col span="12">span: 12</van-col>
|
||||||
|
<van-col span="12">span: 12</van-col>
|
||||||
|
</van-row>
|
||||||
|
</div>
|
||||||
|
</demo-block>
|
||||||
|
|
||||||
<demo-block :title="t('justify')">
|
<demo-block :title="t('justify')">
|
||||||
<van-row justify="center">
|
<van-row justify="center">
|
||||||
<van-col span="6">span: 6</van-col>
|
<van-col span="6">span: 6</van-col>
|
||||||
@ -95,4 +108,10 @@ const t = useTranslate({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.demo-vertical-space {
|
||||||
|
.van-col {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -83,6 +83,42 @@ exports[`should render demo and match snapshot 1`] = `
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<!--[-->
|
||||||
|
<div class="demo-vertical-space">
|
||||||
|
<div class="van-row">
|
||||||
|
<!--[-->
|
||||||
|
<div
|
||||||
|
style
|
||||||
|
class="van-col van-col--12"
|
||||||
|
>
|
||||||
|
<!--[-->
|
||||||
|
span: 12
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style
|
||||||
|
class="van-col van-col--12"
|
||||||
|
>
|
||||||
|
<!--[-->
|
||||||
|
span: 12
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style
|
||||||
|
class="van-col van-col--12"
|
||||||
|
>
|
||||||
|
<!--[-->
|
||||||
|
span: 12
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style
|
||||||
|
class="van-col van-col--12"
|
||||||
|
>
|
||||||
|
<!--[-->
|
||||||
|
span: 12
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<!--[-->
|
<!--[-->
|
||||||
<div class="van-row van-row--justify-center">
|
<div class="van-row van-row--justify-center">
|
||||||
|
@ -49,6 +49,36 @@ exports[`should render demo and match snapshot 1`] = `
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<div class="demo-vertical-space">
|
||||||
|
<div class="van-row">
|
||||||
|
<div
|
||||||
|
class="van-col van-col--12"
|
||||||
|
style="padding-right: 10px; margin-bottom: 20px;"
|
||||||
|
>
|
||||||
|
span: 12
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="padding-left: 10px; margin-bottom: 20px;"
|
||||||
|
class="van-col van-col--12"
|
||||||
|
>
|
||||||
|
span: 12
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="van-col van-col--12"
|
||||||
|
style="padding-right: 10px;"
|
||||||
|
>
|
||||||
|
span: 12
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
style="padding-left: 10px;"
|
||||||
|
class="van-col van-col--12"
|
||||||
|
>
|
||||||
|
span: 12
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="van-row van-row--justify-center">
|
<div class="van-row van-row--justify-center">
|
||||||
<div class="van-col van-col--6">
|
<div class="van-col van-col--6">
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { Col } from '..';
|
import { Col } from '..';
|
||||||
import { Row } from '../../row';
|
import { Row } from '../../row';
|
||||||
import { mount } from '../../../test';
|
import { mount } from '../../../test';
|
||||||
|
import { nextTick } from 'vue';
|
||||||
|
|
||||||
test('should render Col correctly', () => {
|
test('should render Col correctly', () => {
|
||||||
const wrapper = mount(Col, {
|
const wrapper = mount(Col, {
|
||||||
@ -41,3 +42,77 @@ test('should render gutter correctly', () => {
|
|||||||
|
|
||||||
expect(wrapper.html()).toMatchSnapshot();
|
expect(wrapper.html()).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should render vertical space when gutter is an array and provide the second parameter', async () => {
|
||||||
|
const wrapper = mount({
|
||||||
|
render: () => (
|
||||||
|
<Row gutter={[0, 20]}>
|
||||||
|
<Col span="12">12</Col>
|
||||||
|
<Col span="12">12</Col>
|
||||||
|
<Col span="12">12</Col>
|
||||||
|
<Col span="12">12</Col>
|
||||||
|
</Row>
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
|
const fields = wrapper.findAll('.van-col');
|
||||||
|
await nextTick();
|
||||||
|
expect(fields[0].style.marginBottom).toEqual('20px');
|
||||||
|
expect(fields[1].style.marginBottom).toEqual('20px');
|
||||||
|
expect(fields[2].style.marginBottom).toBeFalsy();
|
||||||
|
expect(fields[3].style.marginBottom).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not render vertical space when gutter is an array and provide the second parameter as negative number', async () => {
|
||||||
|
const wrapper = mount({
|
||||||
|
render: () => (
|
||||||
|
<Row gutter={[16, -16]}>
|
||||||
|
<Col span="12">12</Col>
|
||||||
|
<Col span="12">12</Col>
|
||||||
|
<Col span="12">12</Col>
|
||||||
|
<Col span="12">12</Col>
|
||||||
|
</Row>
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
|
const fields = wrapper.findAll('.van-col');
|
||||||
|
await nextTick();
|
||||||
|
fields.forEach((field) => {
|
||||||
|
expect(field.style.marginBottom).toBeFalsy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not render space when gutter is an empty array', async () => {
|
||||||
|
const wrapper = mount({
|
||||||
|
render: () => (
|
||||||
|
<Row gutter={[]}>
|
||||||
|
<Col span="12">12</Col>
|
||||||
|
<Col span="12">12</Col>
|
||||||
|
<Col span="12">12</Col>
|
||||||
|
<Col span="12">12</Col>
|
||||||
|
</Row>
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
|
const field = wrapper.findAll('.van-col')[0];
|
||||||
|
await nextTick();
|
||||||
|
expect(field.style.paddingRight).toBeFalsy();
|
||||||
|
expect(field.style.marginBottom).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should not render vertical space when gutter is an array and provide the second parameter as invalid number', async () => {
|
||||||
|
const wrapper = mount({
|
||||||
|
render: () => (
|
||||||
|
<Row gutter={[0, 'invalid']}>
|
||||||
|
<Col span="12">12</Col>
|
||||||
|
<Col span="12">12</Col>
|
||||||
|
<Col span="12">12</Col>
|
||||||
|
<Col span="12">12</Col>
|
||||||
|
</Row>
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
|
const field = wrapper.findAll('.van-col')[0];
|
||||||
|
await nextTick();
|
||||||
|
expect(field.style.marginBottom).toBeFalsy();
|
||||||
|
});
|
||||||
|
@ -6,20 +6,17 @@ import {
|
|||||||
type InjectionKey,
|
type InjectionKey,
|
||||||
type ExtractPropTypes,
|
type ExtractPropTypes,
|
||||||
} from 'vue';
|
} from 'vue';
|
||||||
import {
|
import { truthProp, makeStringProp, createNamespace } from '../utils';
|
||||||
truthProp,
|
|
||||||
makeStringProp,
|
|
||||||
makeNumericProp,
|
|
||||||
createNamespace,
|
|
||||||
} from '../utils';
|
|
||||||
import { useChildren } from '@vant/use';
|
import { useChildren } from '@vant/use';
|
||||||
|
|
||||||
const [name, bem] = createNamespace('row');
|
const [name, bem] = createNamespace('row');
|
||||||
|
|
||||||
export type RowSpaces = { left?: number; right: number }[];
|
export type RowSpaces = { left?: number; right: number }[];
|
||||||
|
export type VerticalSpaces = { bottom?: number }[];
|
||||||
|
|
||||||
export type RowProvide = {
|
export type RowProvide = {
|
||||||
spaces: ComputedRef<RowSpaces>;
|
spaces: ComputedRef<RowSpaces>;
|
||||||
|
verticalSpaces: ComputedRef<VerticalSpaces>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ROW_KEY: InjectionKey<RowProvide> = Symbol(name);
|
export const ROW_KEY: InjectionKey<RowProvide> = Symbol(name);
|
||||||
@ -37,7 +34,12 @@ export const rowProps = {
|
|||||||
tag: makeStringProp<keyof HTMLElementTagNameMap>('div'),
|
tag: makeStringProp<keyof HTMLElementTagNameMap>('div'),
|
||||||
wrap: truthProp,
|
wrap: truthProp,
|
||||||
align: String as PropType<RowAlign>,
|
align: String as PropType<RowAlign>,
|
||||||
gutter: makeNumericProp(0),
|
gutter: {
|
||||||
|
type: [String, Number, Array] as PropType<
|
||||||
|
string | number | (string | number)[]
|
||||||
|
>,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
justify: String as PropType<RowJustify>,
|
justify: String as PropType<RowJustify>,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -70,7 +72,12 @@ export default defineComponent({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const spaces = computed(() => {
|
const spaces = computed(() => {
|
||||||
const gutter = Number(props.gutter);
|
let gutter = 0;
|
||||||
|
if (Array.isArray(props.gutter)) {
|
||||||
|
gutter = Number(props.gutter[0]) || 0;
|
||||||
|
} else {
|
||||||
|
gutter = Number(props.gutter);
|
||||||
|
}
|
||||||
const spaces: RowSpaces = [];
|
const spaces: RowSpaces = [];
|
||||||
|
|
||||||
if (!gutter) {
|
if (!gutter) {
|
||||||
@ -94,7 +101,25 @@ export default defineComponent({
|
|||||||
return spaces;
|
return spaces;
|
||||||
});
|
});
|
||||||
|
|
||||||
linkChildren({ spaces });
|
const verticalSpaces = computed(() => {
|
||||||
|
const { gutter } = props;
|
||||||
|
const spaces: VerticalSpaces = [];
|
||||||
|
if (Array.isArray(gutter) && gutter.length > 1) {
|
||||||
|
const bottom = Number(gutter[1]) || 0;
|
||||||
|
if (bottom <= 0) {
|
||||||
|
return spaces;
|
||||||
|
}
|
||||||
|
groups.value.forEach((group, index) => {
|
||||||
|
if (index === groups.value.length - 1) return;
|
||||||
|
group.forEach(() => {
|
||||||
|
spaces.push({ bottom });
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return spaces;
|
||||||
|
});
|
||||||
|
|
||||||
|
linkChildren({ spaces, verticalSpaces });
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
const { tag, wrap, align, justify } = props;
|
const { tag, wrap, align, justify } = props;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user