diff --git a/packages/vant/src/col/Col.tsx b/packages/vant/src/col/Col.tsx index 25b03cd34..87ae696a6 100644 --- a/packages/vant/src/col/Col.tsx +++ b/packages/vant/src/col/Col.tsx @@ -4,6 +4,7 @@ import { createNamespace, makeNumericProp, makeStringProp, + extend, } from '../utils'; import { useParent } from '@vant/use'; import { ROW_KEY } from '../row/Row'; @@ -31,15 +32,21 @@ export default defineComponent({ return; } - const { spaces } = parent; - + const { spaces, verticalSpaces } = parent; + let styles = {}; if (spaces && spaces.value && spaces.value[index.value]) { const { left, right } = spaces.value[index.value]; - return { + styles = { paddingLeft: left ? `${left}px` : null, paddingRight: right ? `${right}px` : null, }; } + + const { bottom } = verticalSpaces.value[index.value] || {}; + + return extend(styles, { + marginBottom: bottom ? `${bottom}px` : null, + }); }); return () => { diff --git a/packages/vant/src/col/README.md b/packages/vant/src/col/README.md index 8c2352150..b85c9837d 100644 --- a/packages/vant/src/col/README.md +++ b/packages/vant/src/col/README.md @@ -53,6 +53,20 @@ Set grid spacing using `gutter` attribute. The default value is 0. ``` +### Vertical Spacing + +If you want to set the vertical spacing, you can set `[horizontal, vertical]` as an array. + +```html + + + span: 12 + span: 12 + span: 12 + span: 12 + +``` + ### Justify Content ```html @@ -87,7 +101,7 @@ Set grid spacing using `gutter` attribute. The default value is 0. | Attribute | Description | Type | Default | | --- | --- | --- | --- | -| gutter | Grid spacing(px) | _number \| string_ | - | +| gutter | Grid spacing(px) | _number \| string \| Array_ | - | | tag | Custom element tag | _string_ | `div` | | 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` | diff --git a/packages/vant/src/col/README.zh-CN.md b/packages/vant/src/col/README.zh-CN.md index e72cb40aa..ba912d5c0 100644 --- a/packages/vant/src/col/README.zh-CN.md +++ b/packages/vant/src/col/README.zh-CN.md @@ -52,6 +52,20 @@ Layout 组件提供了 `24列栅格`,通过在 `Col` 上添加 `span` 属性 ``` +### 垂直间距 + +如果需要设置垂直间距,可以使用数组形式设置 `[水平间距, 垂直间距]`。 + +```html + + + span: 12 + span: 12 + span: 12 + span: 12 + +``` + ### 对齐方式 通过 `justify` 属性可以设置主轴上内容的对齐方式,等价于 flex 布局中的 `justify-content` 属性。 @@ -92,7 +106,7 @@ Layout 组件提供了 `24列栅格`,通过在 `Col` 上添加 `span` 属性 | 参数 | 说明 | 类型 | 默认值 | | --- | --- | --- | --- | -| gutter | 列元素之间的间距(单位为 px) | _number \| string_ | - | +| gutter | 列元素之间的间距(单位为 px) | _number \| string \| Array_ | - | | tag | 自定义元素标签 | _string_ | `div` | | justify | 主轴对齐方式,可选值为 `end` `center`
`space-around` `space-between` | _string_ | `start` | | align | 交叉轴对齐方式,可选值为 `center` `bottom` | _string_ | `top` | diff --git a/packages/vant/src/col/demo/index.vue b/packages/vant/src/col/demo/index.vue index 2641a9219..f185f57a6 100644 --- a/packages/vant/src/col/demo/index.vue +++ b/packages/vant/src/col/demo/index.vue @@ -7,10 +7,12 @@ const t = useTranslate({ 'zh-CN': { title2: '在列元素之间增加间距', justify: '对齐方式', + vertical: '垂直间距', }, 'en-US': { title2: 'Column Spacing', justify: 'Justify Content', + vertical: 'Vertical Spacing', }, }); @@ -41,6 +43,17 @@ const t = useTranslate({ + +
+ + span: 12 + span: 12 + span: 12 + span: 12 + +
+
+ span: 6 @@ -95,4 +108,10 @@ const t = useTranslate({ } } } + +.demo-vertical-space { + .van-col { + margin-bottom: 0; + } +} diff --git a/packages/vant/src/col/test/__snapshots__/demo-ssr.spec.ts.snap b/packages/vant/src/col/test/__snapshots__/demo-ssr.spec.ts.snap index ba9e78bc1..f673d6e68 100644 --- a/packages/vant/src/col/test/__snapshots__/demo-ssr.spec.ts.snap +++ b/packages/vant/src/col/test/__snapshots__/demo-ssr.spec.ts.snap @@ -83,6 +83,42 @@ exports[`should render demo and match snapshot 1`] = ` +
+ +
+
+ +
+ + span: 12 +
+
+ + span: 12 +
+
+ + span: 12 +
+
+ + span: 12 +
+
+
+
diff --git a/packages/vant/src/col/test/__snapshots__/demo.spec.ts.snap b/packages/vant/src/col/test/__snapshots__/demo.spec.ts.snap index 81b7cc00f..fbbfba979 100644 --- a/packages/vant/src/col/test/__snapshots__/demo.spec.ts.snap +++ b/packages/vant/src/col/test/__snapshots__/demo.spec.ts.snap @@ -49,6 +49,36 @@ exports[`should render demo and match snapshot 1`] = `
+
+
+
+
+ span: 12 +
+
+ span: 12 +
+
+ span: 12 +
+
+ span: 12 +
+
+
+
diff --git a/packages/vant/src/col/test/index.spec.tsx b/packages/vant/src/col/test/index.spec.tsx index 4ac581e8f..dcc6edd14 100644 --- a/packages/vant/src/col/test/index.spec.tsx +++ b/packages/vant/src/col/test/index.spec.tsx @@ -1,6 +1,7 @@ import { Col } from '..'; import { Row } from '../../row'; import { mount } from '../../../test'; +import { nextTick } from 'vue'; test('should render Col correctly', () => { const wrapper = mount(Col, { @@ -41,3 +42,77 @@ test('should render gutter correctly', () => { expect(wrapper.html()).toMatchSnapshot(); }); + +test('should render vertical space when gutter is an array and provide the second parameter', async () => { + const wrapper = mount({ + render: () => ( + + 12 + 12 + 12 + 12 + + ), + }); + + 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: () => ( + + 12 + 12 + 12 + 12 + + ), + }); + + 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: () => ( + + 12 + 12 + 12 + 12 + + ), + }); + + 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: () => ( + + 12 + 12 + 12 + 12 + + ), + }); + + const field = wrapper.findAll('.van-col')[0]; + await nextTick(); + expect(field.style.marginBottom).toBeFalsy(); +}); diff --git a/packages/vant/src/row/Row.tsx b/packages/vant/src/row/Row.tsx index b8e3b2adb..4982b9fef 100644 --- a/packages/vant/src/row/Row.tsx +++ b/packages/vant/src/row/Row.tsx @@ -6,20 +6,17 @@ import { type InjectionKey, type ExtractPropTypes, } from 'vue'; -import { - truthProp, - makeStringProp, - makeNumericProp, - createNamespace, -} from '../utils'; +import { truthProp, makeStringProp, createNamespace } from '../utils'; import { useChildren } from '@vant/use'; const [name, bem] = createNamespace('row'); export type RowSpaces = { left?: number; right: number }[]; +export type VerticalSpaces = { bottom?: number }[]; export type RowProvide = { spaces: ComputedRef; + verticalSpaces: ComputedRef; }; export const ROW_KEY: InjectionKey = Symbol(name); @@ -37,7 +34,12 @@ export const rowProps = { tag: makeStringProp('div'), wrap: truthProp, align: String as PropType, - gutter: makeNumericProp(0), + gutter: { + type: [String, Number, Array] as PropType< + string | number | (string | number)[] + >, + default: 0, + }, justify: String as PropType, }; @@ -70,7 +72,12 @@ export default defineComponent({ }); 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 = []; if (!gutter) { @@ -94,7 +101,25 @@ export default defineComponent({ 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 () => { const { tag, wrap, align, justify } = props;