历史文章
Form和FormItem
这个组件主要用于表单的布局,下面涉及的其他组件可参考历史文章。
- Form可以接受
width
和labelCol
,分别表示表单宽度和label所占宽度 - FormItem可以接受
width
、labelCol
和label
,前两者可以覆盖父组件传过来的
使用
<s-form width="400px" :labelCol="2">
<s-form-item label="IP地址">
<s-input
:rules="[
{ type: 'required', message: 'ip不能为空' },
{ type: 'ip', message: 'ip格式不对' },
]"
:value="form.ip"
@update="updateForm"
name="ip"
/>
</s-form-item>
</s-form>
封装
SForm.vue
<script lang="ts">
import { h } from "vue"
export default {
name: "SForm",
props: {
width: String, // 表单宽度
labelCol: Number // label所占宽度的比例
},
setup (props, context) {
if (!context.slots || !context.slots.default) return null
// 将form的属性传给formitem
const slots = context.slots.default().map(slot => ({
...slot,
props: {
...props, // 父组件form的属性
...slot.props // 子组件formitem的属性,如果有,会覆盖父组件form的属性(以增强子组件样式的优先级
}
}))
return () => h("div", {
className: "s-form"
}, slots)
}
}
</script>
<style lang="less">
.s-form{
.s-form-item{
margin-top: 10px
}
}
</style>
SFormItem.vue
<template>
<div class="s-form-item" :style="{width}">
<div class="label" :style="{width:labelWidth}">{{label?`${label}:`:' '}}</div>
<slot></slot>
</div>
</template>
<script lang="ts">
export default {
name: "s-form-item",
props: {
label: { // label名称
type: String,
default: ""
},
width: { // 占表格宽度的百分比
type: String,
default: "100%"
},
labelCol: { // label所占宽度
type: Number,
default: 1
}
},
setup (props: {labelCol:number, width:string}) {
const persents = ["10%", "20%", "30%", "40%", "50%", "60%", "80%", "90%", "100%"]
const labelWidth = persents[props.labelCol]
return {
labelWidth,
...props
}
}
}
</script>
<style lang="less" scoped>
.s-form-item{
display: flex;
align-items: baseline;
.label{
text-align: right;
}
}
</style>