mirror of
https://github.com/element-plus/element-plus.git
synced 2026-03-13 07:51:17 +08:00
feat(space): add fill support (#2716)
* feat(space): add fill support * feat(space): Add fill add fillPercentage support * docs(space): Add fillPrecentage explain * refactor(space): rename fillPercentage to fillRatio * docs(space): add description of the fill property * feat(space): add test for fill
This commit is contained in:
@@ -98,4 +98,38 @@ describe('Space.vue', () => {
|
||||
expect(wrapper.element.children).toHaveLength(3)
|
||||
})
|
||||
|
||||
test('fill', async () => {
|
||||
const wrapper = mount(Space, {
|
||||
slots: {
|
||||
default: () =>
|
||||
Array.from({ length: 2 }).map((_, idx) => {
|
||||
return `test${idx}`
|
||||
}),
|
||||
},
|
||||
props: {
|
||||
fill: true,
|
||||
},
|
||||
})
|
||||
|
||||
await nextTick()
|
||||
expect(wrapper.find('.el-space').attributes('style')).toContain(
|
||||
'flex-wrap: wrap',
|
||||
)
|
||||
expect(wrapper.find('.el-space__item').attributes('style')).toContain(
|
||||
'flex-grow: 1',
|
||||
)
|
||||
expect(wrapper.find('.el-space__item').attributes('style')).toContain(
|
||||
'min-width: 100%',
|
||||
)
|
||||
|
||||
// custom fill ratio
|
||||
await wrapper.setProps({
|
||||
fillRatio: 50,
|
||||
})
|
||||
|
||||
await nextTick()
|
||||
expect(wrapper.find('.el-space__item').attributes('style')).toContain(
|
||||
'min-width: 50%',
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -50,6 +50,16 @@ export const defaultProps = {
|
||||
default: false,
|
||||
},
|
||||
|
||||
fill: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
|
||||
fillRatio: {
|
||||
type: Number,
|
||||
default: 100,
|
||||
},
|
||||
|
||||
size: {
|
||||
type: [String, Array, Number] as PropType<
|
||||
ComponentSize | [number, number] | number
|
||||
@@ -73,8 +83,8 @@ export function useSpace(props: ExtractPropTypes<typeof defaultProps>) {
|
||||
const verticalSize = ref(0)
|
||||
|
||||
watch(
|
||||
() => [props.size, props.wrap, props.direction],
|
||||
([size = 'small', wrap, dir]) => {
|
||||
() => [props.size, props.wrap, props.direction, props.fill],
|
||||
([size = 'small', wrap, dir, fill]) => {
|
||||
// when the specified size have been given
|
||||
if (isArray(size)) {
|
||||
const [h = 0, v = 0] = size
|
||||
@@ -88,7 +98,7 @@ export function useSpace(props: ExtractPropTypes<typeof defaultProps>) {
|
||||
val = SizeMap[size as string] || SizeMap.small
|
||||
}
|
||||
|
||||
if (wrap && dir === 'horizontal') {
|
||||
if ((wrap || fill) && dir === 'horizontal') {
|
||||
horizontalSize.value = verticalSize.value = val
|
||||
} else {
|
||||
if (dir === 'horizontal') {
|
||||
@@ -105,9 +115,10 @@ export function useSpace(props: ExtractPropTypes<typeof defaultProps>) {
|
||||
)
|
||||
|
||||
const containerStyle = computed(() => {
|
||||
const wrapKls: CSSProperties = props.wrap
|
||||
? { flexWrap: 'wrap', marginBottom: `-${verticalSize.value}px` }
|
||||
: null
|
||||
const wrapKls: CSSProperties =
|
||||
props.wrap || props.fill
|
||||
? { flexWrap: 'wrap', marginBottom: `-${verticalSize.value}px` }
|
||||
: null
|
||||
const alignment: CSSProperties = {
|
||||
alignItems: props.alignment,
|
||||
}
|
||||
@@ -115,10 +126,16 @@ export function useSpace(props: ExtractPropTypes<typeof defaultProps>) {
|
||||
})
|
||||
|
||||
const itemStyle = computed(() => {
|
||||
return {
|
||||
const itemBaseStyle = {
|
||||
paddingBottom: `${verticalSize.value}px`,
|
||||
marginRight: `${horizontalSize.value}px`,
|
||||
}
|
||||
|
||||
const fillStyle = props.fill
|
||||
? { flexGrow: 1, minWidth: `${props.fillRatio}%` }
|
||||
: null
|
||||
|
||||
return [itemBaseStyle, fillStyle] as Array<CSSProperties>
|
||||
})
|
||||
|
||||
return {
|
||||
|
||||
@@ -269,6 +269,91 @@ Setting this attribute can adjust the alignment of child nodes, the desirable va
|
||||
```
|
||||
:::
|
||||
|
||||
### Fill the container
|
||||
|
||||
Through the `fill` **(Boolean type)** parameter, you can control whether the child node automatically fills the container.
|
||||
|
||||
In the following example, when set to `fill`, the width of the child node will automatically adapt to the width of the container.
|
||||
|
||||
:::demo Use fill to automatically fill the container with child nodes
|
||||
|
||||
```html
|
||||
<template>
|
||||
<div>
|
||||
<div style="margin-bottom:15px">
|
||||
fill: <el-switch v-model="fill"></el-switch>
|
||||
</div>
|
||||
<el-space :fill="fill" wrap>
|
||||
<el-card class="box-card" v-for="i in 3" :key="i">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>Card name</span>
|
||||
<el-button class="button" type="text">Operation button</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<div v-for="o in 4" :key="o" class="text item">
|
||||
{{ 'List item ' + o }}
|
||||
</div>
|
||||
</el-card>
|
||||
</el-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return { fill: true }
|
||||
},
|
||||
}
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
You can also use the `fillRatio` parameter to customize the filling ratio. The default value is `100`, which represents filling based on the width of the parent container at `100%`.
|
||||
|
||||
It should be noted that the expression of horizontal layout and vertical layout is slightly different, the specific effect can be viewed in the following example.
|
||||
|
||||
:::demo Use fillRatio to customize the fill ratio
|
||||
|
||||
```html
|
||||
<template>
|
||||
<div>
|
||||
<div style="margin-bottom: 15px">
|
||||
direction:
|
||||
<el-radio v-model="direction" label="horizontal">horizontal</el-radio>
|
||||
<el-radio v-model="direction" label="vertical">vertical</el-radio>
|
||||
</div>
|
||||
<div style="margin-bottom: 15px">
|
||||
fillRatio:<el-slider v-model="fillRatio"></el-slider>
|
||||
</div>
|
||||
<el-space fill wrap :fillRatio="fillRatio" :direction="direction" style=" width: 100%">
|
||||
<el-card class="box-card" v-for="i in 5" :key="i">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>Card name</span>
|
||||
<el-button class="button" type="text">Operation button</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<div v-for="o in 4" :key="o" class="text item">
|
||||
{{ 'List item ' + o }}
|
||||
</div>
|
||||
</el-card>
|
||||
</el-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return { direction: 'horizontal', fillRatio: 30 }
|
||||
},
|
||||
}
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
### Space Attributes
|
||||
|
||||
| Attribute | Description | Type | Available value | Default |
|
||||
@@ -281,7 +366,9 @@ Setting this attribute can adjust the alignment of child nodes, the desirable va
|
||||
| spacer | Spacer | string / number / VNode | - | - |
|
||||
| size | Spacing size | string / number / [number, number] | - | 'small' |
|
||||
| wrap | Auto wrapping | boolean | true / false | false |
|
||||
### Space Slots
|
||||
| Name | Description |
|
||||
| fill | Whether to fill the container | boolean | true / false | false |
|
||||
| fillRatio | Ratio of fill | number | - | 100 |
|
||||
### Space Slot
|
||||
| name | description |
|
||||
|----|----|
|
||||
| default | Items to be spaced |
|
||||
|
||||
@@ -269,6 +269,91 @@ Setting this attribute can adjust the alignment of child nodes, the desirable va
|
||||
```
|
||||
:::
|
||||
|
||||
### Fill the container
|
||||
|
||||
Through the `fill` **(Boolean type)** parameter, you can control whether the child node automatically fills the container.
|
||||
|
||||
In the following example, when set to `fill`, the width of the child node will automatically adapt to the width of the container.
|
||||
|
||||
:::demo Use fill to automatically fill the container with child nodes
|
||||
|
||||
```html
|
||||
<template>
|
||||
<div>
|
||||
<div style="margin-bottom:15px">
|
||||
fill: <el-switch v-model="fill"></el-switch>
|
||||
</div>
|
||||
<el-space :fill="fill" wrap>
|
||||
<el-card class="box-card" v-for="i in 3" :key="i">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>Card name</span>
|
||||
<el-button class="button" type="text">Operation button</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<div v-for="o in 4" :key="o" class="text item">
|
||||
{{ 'List item ' + o }}
|
||||
</div>
|
||||
</el-card>
|
||||
</el-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return { fill: true }
|
||||
},
|
||||
}
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
You can also use the `fillRatio` parameter to customize the filling ratio. The default value is `100`, which represents filling based on the width of the parent container at `100%`.
|
||||
|
||||
It should be noted that the expression of horizontal layout and vertical layout is slightly different, the specific effect can be viewed in the following example.
|
||||
|
||||
:::demo Use fillRatio to customize the fill ratio
|
||||
|
||||
```html
|
||||
<template>
|
||||
<div>
|
||||
<div style="margin-bottom: 15px">
|
||||
direction:
|
||||
<el-radio v-model="direction" label="horizontal">horizontal</el-radio>
|
||||
<el-radio v-model="direction" label="vertical">vertical</el-radio>
|
||||
</div>
|
||||
<div style="margin-bottom: 15px">
|
||||
fillRatio:<el-slider v-model="fillRatio"></el-slider>
|
||||
</div>
|
||||
<el-space fill wrap :fillRatio="fillRatio" :direction="direction" style=" width: 100%">
|
||||
<el-card class="box-card" v-for="i in 5" :key="i">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>Card name</span>
|
||||
<el-button class="button" type="text">Operation button</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<div v-for="o in 4" :key="o" class="text item">
|
||||
{{ 'List item ' + o }}
|
||||
</div>
|
||||
</el-card>
|
||||
</el-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return { direction: 'horizontal', fillRatio: 30 }
|
||||
},
|
||||
}
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
### Space Attributes
|
||||
|
||||
| Attribute | Description | Type | Available value | Defaults |
|
||||
@@ -281,6 +366,8 @@ Setting this attribute can adjust the alignment of child nodes, the desirable va
|
||||
| spacer | Spacer | string / number / VNode | - | - |
|
||||
| size | Spacing size | string / number / [number, number] | - | 'small' |
|
||||
| wrap | Auto wrapping | boolean | true / false | false |
|
||||
| fill | Whether to fill the container | boolean | true / false | false |
|
||||
| fillRatio | Ratio of fill | number | - | 100 |
|
||||
### Space Slot
|
||||
| name | description |
|
||||
|----|----|
|
||||
|
||||
@@ -269,6 +269,91 @@ Setting this attribute can adjust the alignment of child nodes, the desirable va
|
||||
```
|
||||
:::
|
||||
|
||||
### Fill the container
|
||||
|
||||
Through the `fill` **(Boolean type)** parameter, you can control whether the child node automatically fills the container.
|
||||
|
||||
In the following example, when set to `fill`, the width of the child node will automatically adapt to the width of the container.
|
||||
|
||||
:::demo Use fill to automatically fill the container with child nodes
|
||||
|
||||
```html
|
||||
<template>
|
||||
<div>
|
||||
<div style="margin-bottom:15px">
|
||||
fill: <el-switch v-model="fill"></el-switch>
|
||||
</div>
|
||||
<el-space :fill="fill" wrap>
|
||||
<el-card class="box-card" v-for="i in 3" :key="i">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>Card name</span>
|
||||
<el-button class="button" type="text">Operation button</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<div v-for="o in 4" :key="o" class="text item">
|
||||
{{ 'List item ' + o }}
|
||||
</div>
|
||||
</el-card>
|
||||
</el-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return { fill: true }
|
||||
},
|
||||
}
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
You can also use the `fillRatio` parameter to customize the filling ratio. The default value is `100`, which represents filling based on the width of the parent container at `100%`.
|
||||
|
||||
It should be noted that the expression of horizontal layout and vertical layout is slightly different, the specific effect can be viewed in the following example.
|
||||
|
||||
:::demo Use fillRatio to customize the fill ratio
|
||||
|
||||
```html
|
||||
<template>
|
||||
<div>
|
||||
<div style="margin-bottom: 15px">
|
||||
direction:
|
||||
<el-radio v-model="direction" label="horizontal">horizontal</el-radio>
|
||||
<el-radio v-model="direction" label="vertical">vertical</el-radio>
|
||||
</div>
|
||||
<div style="margin-bottom: 15px">
|
||||
fillRatio:<el-slider v-model="fillRatio"></el-slider>
|
||||
</div>
|
||||
<el-space fill wrap :fillRatio="fillRatio" :direction="direction" style=" width: 100%">
|
||||
<el-card class="box-card" v-for="i in 5" :key="i">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>Card name</span>
|
||||
<el-button class="button" type="text">Operation button</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<div v-for="o in 4" :key="o" class="text item">
|
||||
{{ 'List item ' + o }}
|
||||
</div>
|
||||
</el-card>
|
||||
</el-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return { direction: 'horizontal', fillRatio: 30 }
|
||||
},
|
||||
}
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
### Space Attributes
|
||||
|
||||
| Attribute | Description | Type | Available value | Defaults |
|
||||
@@ -281,6 +366,8 @@ Setting this attribute can adjust the alignment of child nodes, the desirable va
|
||||
| spacer | Spacer | string / number / VNode | - | - |
|
||||
| size | Spacing size | string / number / [number, number] | - | 'small' |
|
||||
| wrap | Auto wrapping | boolean | true / false | false |
|
||||
| fill | Whether to fill the container | boolean | true / false | false |
|
||||
| fillRatio | Ratio of fill | number | - | 100 |
|
||||
### Space Slot
|
||||
| name | description |
|
||||
|----|----|
|
||||
|
||||
@@ -269,6 +269,91 @@ Setting this attribute can adjust the alignment of child nodes, the desirable va
|
||||
```
|
||||
:::
|
||||
|
||||
### Fill the container
|
||||
|
||||
Through the `fill` **(Boolean type)** parameter, you can control whether the child node automatically fills the container.
|
||||
|
||||
In the following example, when set to `fill`, the width of the child node will automatically adapt to the width of the container.
|
||||
|
||||
:::demo Use fill to automatically fill the container with child nodes
|
||||
|
||||
```html
|
||||
<template>
|
||||
<div>
|
||||
<div style="margin-bottom:15px">
|
||||
fill: <el-switch v-model="fill"></el-switch>
|
||||
</div>
|
||||
<el-space :fill="fill" wrap>
|
||||
<el-card class="box-card" v-for="i in 3" :key="i">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>Card name</span>
|
||||
<el-button class="button" type="text">Operation button</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<div v-for="o in 4" :key="o" class="text item">
|
||||
{{ 'List item ' + o }}
|
||||
</div>
|
||||
</el-card>
|
||||
</el-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return { fill: true }
|
||||
},
|
||||
}
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
You can also use the `fillRatio` parameter to customize the filling ratio. The default value is `100`, which represents filling based on the width of the parent container at `100%`.
|
||||
|
||||
It should be noted that the expression of horizontal layout and vertical layout is slightly different, the specific effect can be viewed in the following example.
|
||||
|
||||
:::demo Use fillRatio to customize the fill ratio
|
||||
|
||||
```html
|
||||
<template>
|
||||
<div>
|
||||
<div style="margin-bottom: 15px">
|
||||
direction:
|
||||
<el-radio v-model="direction" label="horizontal">horizontal</el-radio>
|
||||
<el-radio v-model="direction" label="vertical">vertical</el-radio>
|
||||
</div>
|
||||
<div style="margin-bottom: 15px">
|
||||
fillRatio:<el-slider v-model="fillRatio"></el-slider>
|
||||
</div>
|
||||
<el-space fill wrap :fillRatio="fillRatio" :direction="direction" style=" width: 100%">
|
||||
<el-card class="box-card" v-for="i in 5" :key="i">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>Card name</span>
|
||||
<el-button class="button" type="text">Operation button</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<div v-for="o in 4" :key="o" class="text item">
|
||||
{{ 'List item ' + o }}
|
||||
</div>
|
||||
</el-card>
|
||||
</el-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return { direction: 'horizontal', fillRatio: 30 }
|
||||
},
|
||||
}
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
### Space Attributes
|
||||
|
||||
| Attribute | Description | Type | Available value | Defaults |
|
||||
@@ -281,6 +366,8 @@ Setting this attribute can adjust the alignment of child nodes, the desirable va
|
||||
| spacer | Spacer | string / number / VNode | - | - |
|
||||
| size | Spacing size | string / number / [number, number] | - | 'small' |
|
||||
| wrap | Auto wrapping | boolean | true / false | false |
|
||||
| fill | Whether to fill the container | boolean | true / false | false |
|
||||
| fillRatio | Ratio of fill | number | - | 100 |
|
||||
### Space Slot
|
||||
| name | description |
|
||||
|----|----|
|
||||
|
||||
@@ -269,6 +269,91 @@ export default {
|
||||
```
|
||||
:::
|
||||
|
||||
### 自动填充容器
|
||||
|
||||
通过 `fill` **(布尔类型)** 参数可以控制子节点是否自动填充容器
|
||||
|
||||
下面的例子中,当设置为 `fill` 时,子节点的宽度会自动适配容器的宽度
|
||||
|
||||
:::demo 用 fill 让子节点自动填充容器
|
||||
|
||||
```html
|
||||
<template>
|
||||
<div>
|
||||
<div style="margin-bottom:15px">
|
||||
fill: <el-switch v-model="fill"></el-switch>
|
||||
</div>
|
||||
<el-space :fill="fill" wrap>
|
||||
<el-card class="box-card" v-for="i in 3" :key="i">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>Card name</span>
|
||||
<el-button class="button" type="text">Operation button</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<div v-for="o in 4" :key="o" class="text item">
|
||||
{{ 'List item ' + o }}
|
||||
</div>
|
||||
</el-card>
|
||||
</el-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return { fill: true }
|
||||
},
|
||||
}
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
也可以使用 `fillRatio` 参数,自定义填充的比例,默认值为 `100`,代表基于父容器宽度的 `100%` 进行填充
|
||||
|
||||
需要注意的是,水平布局和垂直布局的表现形式稍有不同,具体的效果可以查看下面的例子
|
||||
|
||||
:::demo 用 fillRatio 自定义填充比例
|
||||
|
||||
```html
|
||||
<template>
|
||||
<div>
|
||||
<div style="margin-bottom: 15px">
|
||||
direction:
|
||||
<el-radio v-model="direction" label="horizontal">horizontal</el-radio>
|
||||
<el-radio v-model="direction" label="vertical">vertical</el-radio>
|
||||
</div>
|
||||
<div style="margin-bottom: 15px">
|
||||
fillRatio:<el-slider v-model="fillRatio"></el-slider>
|
||||
</div>
|
||||
<el-space fill wrap :fillRatio="fillRatio" :direction="direction" style=" width: 100%">
|
||||
<el-card class="box-card" v-for="i in 5" :key="i">
|
||||
<template #header>
|
||||
<div class="card-header">
|
||||
<span>Card name</span>
|
||||
<el-button class="button" type="text">Operation button</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<div v-for="o in 4" :key="o" class="text item">
|
||||
{{ 'List item ' + o }}
|
||||
</div>
|
||||
</el-card>
|
||||
</el-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return { direction: 'horizontal', fillRatio: 30 }
|
||||
},
|
||||
}
|
||||
</script>
|
||||
```
|
||||
:::
|
||||
|
||||
### Space Attributes
|
||||
|
||||
| 参数 | 说明 | 类型 | 可选值 | 默认值 |
|
||||
@@ -281,6 +366,8 @@ export default {
|
||||
| spacer | 间隔符 | string / number / VNode | - | - |
|
||||
| size | 间隔大小 | string / number / [number, number] | - | 'small' |
|
||||
| wrap | 设置是否自动折行 | boolean | true / false | false |
|
||||
| fill | 子元素是否填充父容器 | boolean | true / false | false |
|
||||
| fillRatio | 填充父容器的比例 | number | - | 100 |
|
||||
### Space Slot
|
||||
| name | 说明 |
|
||||
|----|----|
|
||||
|
||||
Reference in New Issue
Block a user