组件
组件的功能与 composable 相同,但无需在 <script> 中编写代码:只需用 useForm 创建表单,其余都在模板中完成。字段会通过上层的 <TvForm> 自动找到表单。
vue
<script setup lang="ts">
import { useForm, TvForm, TvField, TvError } from 'tinyval-vue';
const form = useForm(Signup, { initial: { name: '', email: '', plan: 'free', terms: false } });
const save = (data) => api.post('/signup', data); // 422 from Laravel is shown at the fields automatically
</script>
<template>
<TvForm :form="form" @submit="save">
<TvField name="name" placeholder="Name" />
<TvError name="name" />
<TvField name="email" type="email" />
<TvError name="email" />
<TvField name="plan" type="radio" value="free" /> Free
<TvField name="plan" type="radio" value="pro" /> Pro
<TvField name="terms" type="checkbox" /> I accept the terms
<button :disabled="form.submitting">Sign up</button>
</TvForm>
</template>TvForm
渲染 <form novalidate>,通过 handleSubmit 提交,并把表单提供给嵌套字段。
| Prop / 事件 | 说明 |
|---|---|
form | 由 useForm 创建的表单。必填 |
@submit | 以校验后的数据调用。如果返回 Promise,在其完成前 form.submitting 为 true;带 422 响应的拒绝会被分配到各字段 |
@invalid | 校验失败时以错误调用 |
默认插槽接收 { form }。
TvField
通过 name 与表单绑定的字段。其他属性(placeholder、class、autocomplete…)会传递给元素。
| Prop | 说明 |
|---|---|
name | 字段路径:email、address.city、items.0.title |
as | 'input'(默认)、'textarea'、'select',或支持 v-model 的 UI 组件 |
type | <input> 类型:checkbox、radio、file 等 |
value | radio 和复选框组的选项值 |
multiple | 多个文件或 <select> 多选 |
form | 显式传入表单 —— 当上层没有 <TvForm> 时 |
| 字段 | 表单中的值 |
|---|---|
<TvField name="bio" as="textarea" /> | 字符串 |
<TvField name="terms" type="checkbox" /> | true / false |
<TvField name="tags" type="checkbox" value="js" /> | 已勾选 value 的数组 |
<TvField name="plan" type="radio" value="pro" /> | 选中按钮的 value |
<TvField name="city" as="select"> + <option> | 选中项的值 |
<TvField name="langs" as="select" multiple> | 值的数组 |
<TvField name="avatar" type="file" /> | File 或 null;使用 multiple 时为数组 |
<TvField name="email" :as="ElInput" /> | 组件的 v-model |
可以通过插槽渲染完全自定义的标记 —— 插槽接收 field(用于 v-bind)、value、setValue、error、errorId、touched、dirty:
vue
<TvField name="email" v-slot="{ field, error, errorId }">
<el-form-item :error="error">
<el-input v-bind="field" />
</el-form-item>
</TvField>TvError
应显示时的字段错误文本。渲染 <span role="alert">,其 id 与字段的 aria-describedby 对应。
| Prop | 说明 |
|---|---|
name | 字段路径 |
as | 标签,默认为 span |
form | 显式传入表单 —— 当上层没有 <TvForm> 时 |
自定义标记可使用插槽 { message, id }。
vue
<TvError name="email" v-slot="{ message, id }">
<p :id="id" class="text-red-600">⚠ {{ message }}</p>
</TvError>TvFieldArray
字段列表 —— 插槽接收 useFieldArray 返回的全部内容:fields、append、remove、move…
vue
<TvFieldArray name="items" v-slot="{ fields, append, remove }">
<div v-for="f in fields" :key="f.key">
<TvField :name="`${f.path}.title`" />
<TvError :name="`${f.path}.title`" />
<button type="button" @click="remove(f.index)">×</button>
</div>
<button type="button" @click="append({ title: '' })">+</button>
</TvFieldArray>