cl-form
自定义表单组件
@cool-vue/crud@6.x
新增 ref 参数,方便获取组件实例
useForm()
cl-form
标签绑定 ref
值后使用 useForm
加载组件
const
定义必须与ref
一致
<template>
<cl-form ref="Form"></cl-form>
</template>
<script lang="ts" setup>
import { useForm } from "@cool-vue/crud";
const Form = useForm();
</script>
如果存在使用多个 cl-form
组件的情况,配置不同的 ref
值即可:
<template>
<cl-form ref="UserForm"></cl-form>
<cl-form ref="GoodsForm"></cl-form>
</template>
<script lang="ts" setup>
import { useForm } from "@cool-vue/crud";
const UserForm = useForm();
const GoodsForm = useForm();
</script>
TIP
子组件可以也可以使用 const Form = useForm()
获取 cl-form
实例。同样 Ref 上的值与方法都能使用
<template>
<cl-form ref="Form"></cl-form>
</template>
<script lang="ts" setup>
import { useForm } from "@cool-vue/crud";
const Form = useForm();
function open() {
Form.value.open({
items: [
{
label: "昵称",
prop: "name",
component: {
vm: Test
}
}
]
});
}
</script>
Test.vue
<template>
<!-- 绑定name -->
<el-input v-model="Form.form.name" />
</template>
<script lang="ts" setup>
import { useForm } from "@cool-vue/crud";
const Form = useForm();
</script>
示例
基础用法
分组显示
配置 type
参数为 tabs
,labels
作为分组列表:
- label 分组名称
- value 分组标识
获取组件实例
在部分情况下,想要获取到组件的实例,有 2 种方法:
ref
参数
const { refs, setRefs } = useCool();
const Form = useForm({
items: [
{
label: "昵称",
prop: "name",
component: {
name: "el-input",
ref: setRefs("name")
}
}
],
on: {
open() {
refs.name.focus();
}
}
});
- 插槽
<cl-form ref="Form">
<template #slot-name="{ scope }">
<el-input :ref="setRefs('name')" v-model="scope.name" />
</template>
</cl-form>
钩子函数
open(data)
打开后close(done)
关闭前submit(data, { close, done })
提交时
参数
参数 | 说明 | 类型 | 可选值 | 默认值 |
---|---|---|---|---|
inner | 是否只显示表单 | boolean | false | |
inline | 是否内联表单 | boolean | false |
Ref
方法名 | 说明 | 参数 |
---|---|---|
form | 表单值 | |
open | 打开表单 | Options |
close | 关闭表单 | |
done | 关闭 saving 状态 | |
clear | 清空表单值 | |
reset | 重置表单值 | |
showLoading | 显示加载框 | |
hiddenLoading | 隐藏加载框 | |
setTitle | 设置标题 | title |
setData | 根据对象层级设置参数 | prop, value |
setOptions | 设置下拉列表 | prop, value |
setProps | 设置组件参数 | prop, props |
getForm | 获取表单值 | prop? |
setForm | 设置表单值 | prop, value |
toggleItem | 切换 hidden 值 | prop, flag? |
hideItem | 隐藏 | props |
showItem | 显示 | props |
resetFields | 对整个表单进行重置 | |
clearValidate | 移除表单项的校验结果 | props: array / string |
validateField | 对部分表单字段进行校验的方法 | props: array / string, callback |
validate | 对整个表单进行校验的方法 | callback |
changeTab | 切换选项栏 | name |
submit | 表单提交 | callback(data) |
OpenOptions
参数 | 说明 | 类型 | 可选值 | 默认值 |
---|---|---|---|---|
title | 标题 | string | ||
width | 宽度 | string | ||
items | 表单项 | Items | ||
props | el-form 参数 | FormProps | ||
form | 表单值 | object | ||
on | 事件监听 | object | ||
on.open | 表单打开 | function(form) | ||
on.close | 表单关闭 | function(done) | ||
on.submit | 表单提交 | function(data, {close,done}) | ||
dialog | 对话框参数 | object | ||
dialog.hiddenHeader | 隐藏头部 | boolean | false | |
dialog.controls | 头部操作按钮 | array | ["fullscreen", "close"] | |
op | 底部操作按钮 | object | ||
op.hidden | 是否隐藏 | boolean | false | |
op.saveButtonText | 保存按钮文案 | string | 保存 | |
op.closeButtonText | 关闭按钮文案 | string | 取消 | |
op.buttons | 按钮组 | array | ["close", "save"] |
FormProps
参数 | 说明 | 类型 | 可选值 | 默认值 |
---|---|---|---|---|
inline | 行内表单模式 | boolean | false | |
label-width | 表单域标签的宽度 | string | 120px | |
label-position | 表单域标签的位置 | string | left / top / right | right |
label-suffix | 表单域标签的后缀 | string | ||
hide-required-asterisk | 是否显示必填字段的标签旁边的红色星号 | boolean | false | |
show-message | 是否显示校验错误信息 | boolean | true | |
inline-message | 是否以行内形式展示校验信息 | boolean | false | |
status-icon | 是否在输入框中显示校验结果反馈图标 | boolean | false | |
validate-on-rule-change | 是否在 rules 属性改变后立即触发一次验证 | boolean | true | |
size | 用于控制该表单内组件的尺寸 | string | large / default /small | default |
disabled | 是否禁用该表单内的所有组件 | boolean | false |
Items
参数 | 说明 | 类型 | 可选值 | 默认值 |
---|---|---|---|---|
type | 类型 | string | tabs | |
prop | 字段 | string | ||
value | 默认值,对应组件 component 的 v-model | any | ||
props | 对应 component 组件的 prop 参数 | object | ||
label | 标签文本 | string, RenderOptions | ||
component | 组件渲染 | object | ||
component.name | 组件标签名、 slot 名 | string | ||
component.vm | 组件渲染节点 | object | ||
component.style | 组件样式 | object | ||
component.props | 组件参数 | object | ||
component.ref | 组件绑定值 | setRefs(string) | ||
prepend | 添加到 component 组件前 | object | ||
append | 添加到 component 组件后 | object | ||
collapse | 是否折叠 | boolean | ||
rules | 验证规则 | array, object | ||
required | 是否必填,自动填充 rules | boolean | false | |
hidden | 是否隐藏 | boolean, string, function | false | |
span | 栅格占据的列数 | number | 24 | |
flex | 是否横向拉升元素 | boolean | true | |
group | 分组显示 | string | ||
hook | 钩子模式 | array / string / object / function | ||
hook.bind | 表单值绑定时触发数据更新 | array / string / object / function | ||
hook.submit | 表单提交时触发数据更新 | array / string / object / function |
TIP
- 静态配置
const Form = useForm();
Form.value?.open({
items: [
{
label: "昵称",
prop: "nickName",
component: {
name: "el-input"
}
}
]
});
- 动态配置,如在
upsert
中新增、编辑显示不同的状态
const Form = useForm();
Form.value?.open({
items: [
({ scope }) => {
// scope 表单值
return {
label: "昵称",
prop: "nickName",
component: {
name: "el-input"
}
};
}
]
});
Component
表单项的元素通过 component
渲染,该参数支持 4 中渲染方式:
- 绑定标签
该组件必须是全局注册
该方式会自动绑定组件的
v-model
props
为该组件参数对
el-select
el-checkbox-group
el-radio-group
支持配置列表数据options
Form.value?.open({
items: [
{
label: "昵称",
prop: "name",
component: {
name: "el-input",
props: {
clearable: true
}
}
}
]
});
Form.value?.open({
items: [
{
label: "职业",
prop: "work",
component: {
name: "el-select",
options: [
{
label: "程序员",
value: 0
},
{
label: "设计师",
value: 1
}
]
}
}
]
});
- 万能插槽,适用于各种场景
必须以
slot-
开头命名scope
为表单值
Form.value?.open({
items: [
{
label: "昵称",
prop: "name",
component: {
name: "slot-name"
}
}
]
});
<cl-form>
<template #slot-name="{ scope }">
<el-input v-model="scope.name" />
</template>
</cl-form>
- 使用
tsx
标签渲染
lang
必须为tsx
这种方式下无法绑定
v-model
<script lang="tsx" setup>
Form.value?.open({
items: [
{
label: "昵称",
prop: "name",
component: <el-alert title="无效昵称" />
}
]
});
</script>
- 使用
.vue
、.tsx
文件或者render
方法
绑定在
vm
上该方式会自动绑定组件的
v-model
,但是需要自己处理update:modelValue
值的接收及更新props
为该组件参数
Form.value?.open({
items: [
{
label: "昵称",
prop: "name",
component: {
vm: {
name: "test-name",
// 接收值
props: {
modelValue: String
},
setup(props: any, { emit }: any) {
const value = ref<string>();
// 监听值变化,如果在 cl-upsert 下,第一次会为 undefined
watch(
() => props.modelValue,
(val) => {
value.value = val;
},
{
immediate: true
}
);
return {
value,
// 更新值
onInput(val: string) {
emit("update:modelValue", val);
}
};
},
render(ctx: any) {
// 绑定值
return <el-input v-model={ctx.value} onInput={ctx.onInput} />;
// 也可以使用 h 的方式渲染
// return h(resolveComponent('el-input'))
}
}
props: {
type: "a"
}
}
}
]
});
import Test from "./test.vue";
Form.value?.open({
items: [
{
label: "昵称",
prop: "name",
component: {
vm: Test,
props: {
type: "a"
}
}
}
]
});
Hook
该参数设计于为了更方便的接收、提交参数。
当有这么一个场景,后端返回给你的 idList
是用 ,
拼接的,如:
{
idList: "1,2,3";
}
前端是需要你用 el-select
的组件展示,且需要多选模式 multiple
。那一般的操作都是获取数据后对数据 split
分割,再绑定于 value
上。
这时候就可以用到 hook
参数,它可以在绑定 value
的时候预先处理数据:
{
label: '角色列表',
prop: 'ids',
hook: {
bind: ['split', 'number'], // 通道流程,分割 -> 转成number -> 绑定值
},
component: {
name: 'el-select',
props: {
multiple: true
},
options: [
{
label: "李逍遥",
value: 1
},
{
label: "景天",
value: 2
},
{
label: "宇文拓",
value: 3
}
]
}
}
// 绑定的数据:
{
ids: [1, 2, 3]
}
当然有些 讨厌
的后端又想让你以 1,2,3
逗号拼接的方式提交。那你也可以用 hook
参数处理,用 join
的方式拼接:
{
label: '角色列表',
prop: 'ids',
hook: {
bind: ['split', 'number'], // 绑定通道流程,分割 -> 转成number -> 绑定值
submit: ['join'], // 提交通道流程,逗号拼接 -> 提交
},
component: {
name: 'el-select',
props: {
multiple: true
},
options: [
{
label: "李逍遥",
value: 1
},
{
label: "景天",
value: 2
},
{
label: "宇文拓",
value: 3
}
]
}
}
// 提交的数据:
{
ids: '1,2,3'
}
hook 已有的方法
名称 | 说明 |
---|---|
number | 转成 number , 如果值是数组,那每一项都会被操作到 |
string | 转成 string , 如果值是数组,那每一项都会被操作到 |
split | 字符串以 , 分割为数组 |
join | 数组以 , 拼接为字符串 |
boolean | 转成 boolean |
booleanNumber | 接收一个 boolean 值,返回 1 或 0 |
datetimeRange | 在提交中会根据 prop 自动转换为 start[prop] 和 end[prop] |
splitJoin | 绑定时 split(",") ,提交时 join(",") |
json | 绑定时 JSON.parse() ,提交时 JSON.stringify() |
empty | 等于"" 时修改为 undefined |
当然你也可以用自定义:
// 例如 value 为:"1,2,3"
{
hook: {
bind: (value, form) => {
// value 是与 prop 绑定的值
// form 是表单值
return value.split(",").map(Number).filter(Boolean); // 结果为:[1, 2, 3]
},
submit: (value, form) => {
return value.join(","); // 结果为:"1,2,3"
}
}
}
也可以多个处理:
hook: {
bind: [
'split', // 1 分割
() => {
// 2 自定义
},
'number', // 3 转成 number
],
submit: [
'join', // 1 拼接
() => {
// 2 自定义
}
]
}
Hidden
// 默认填入 boolean
{
label: "姓名",
prop: "name",
hidden: false
}
// scope 为表单数据,自定义返回值
{
label: "姓名",
prop: "name",
hidden: ({ scope }) => {
return !scope.showName
}
}
// 使用 ref
const isHidden = ref(false)
{
label: "姓名",
prop: "name",
hidden: isHidden
}
// 使用 computed
const isHidden = computed(() => false)
{
label: "姓名",
prop: "name",
hidden: isHidden
}