自定义控件
widget
作为表单的基本渲染单元,除了 SchemaForm 提供的内置控件外,还提供了注册控件的机制
示例
在内置控件不满足场景的情况下,通过 SchemaForm 的 widgets
注册控件,然后通过 schema 中的 widget
字段指定对应的 key 并使用;
注册 & 使用
操作流程
- 引入组件
- 注册组件
- 在
schema
中指定widget
的 key
vue 5
<template>
<SchemaForm
v-model="formData"
:schema="schema"
:widgets="widgets"
/>
</template>
<script setup>
import { ref } from 'vue';
import Rate from './Rate';
import SchemaForm from 'v3-schema-form';
const formData = ref({
rate: 3,
});
const schema = {
type: 'object',
properties: {
name: {
type: 'string',
title: 'Rate',
widget: 'rate'
required: true,
},
}
};
const widgets = {
rate: Rate
}
</script>
自定义控件的 props
每个自定义控件都是通过 v-model
的双向绑定来关联到 SchemaForm 的表单数据 所以每个控件需要定义 modelValue
和 update:modelValue
,也就是 v-model
的对外实现
例如我们要注册一个 Rate 控件,首先要实现一个 Rate 控件:
tsx
// ./Rate
import { defineComponent, computed } from 'vue';
import { Rate } from 'vant';
import { useAddon } from 'v3-schema-form';
export default defineComponent({
emits: ['update:modelValue'],
props: {
modelValue: String,
},
setup: (props, { emit }) => {
const addon = useAddon();
const value = computed({
get: () => props.modelValue,
set: (value: string) => {
emit('update:modelValue', value);
},
});
return () => (
<div>
<Rate
v-model={value.value}
{...addon.value.props}
/>
</div>
);
},
});
定制自定义控件的逻辑(useAddon)
通过 useAddon 可以拿到整个 SchemaForm 操作方法和属性,帮助定制一些特殊场景的逻辑
tips
注意 useAddon 拿到的是响应式数据,使用 ES6 解构会破坏掉响应式
js
const addon = useAddon();
// 触发整个表单的校验
addon.value.validate();
// 获取表单项的值
addon.value.getFormData().xxx;
// 当前是否为禁用状态
addon.value.disabled;
type
ts
interface FieldWidgetAddon<FD extends FormData> {
/** 控件对应的 schema */
schema: Schema;
disabled: boolean;
readonly: boolean;
/** 对应字段code */
name: string;
/** 根节点的 schema */
rootSchema: Schema;
placeholder?: string;
className?: string;
required?: boolean;
props?: Record<string, any>;
/** 设置表单值 */
setFormData: (newFormData: Partial<FD>) => void;
/** 获取当前表单值 */
getFormData: () => FD;
/** 触发整个表单校验 */
validate: (scrollToError?: boolean) => Promise<ErrorMessage[]>;
/** 触发指定字段的校验 */
validateFields: (fields: (keyof FD)[], scrollToError?: boolean) => Promise<ErrorMessage[]>;
}