Skip to content

分步表单 ​

较长的表单适合拆分为多个步骤。所有步骤共用一个 Schema 和一个表单,form.validate(paths) 只检查当前步骤的字段 —— 用户不会过早看到后续步骤的错误。

示例 ​

vue
<script setup lang="ts">
import { ref } from 'vue';
import { object, string, pipe, email, minLength, coerce, literal } from 'tinyval';
import { useForm } from 'tinyval-vue';

const Order = object({
  name: pipe(string(), minLength(2)),
  email: pipe(string(), email()),
  city: string(),
  address: string(),
  date: coerce.date(),
  terms: literal(true),
});

const steps = [['name', 'email'], ['city', 'address'], ['date', 'terms']];
const step = ref(0);

const form = useForm(Order, {
  initial: { name: '', email: '', city: '', address: '', date: '', terms: false },
});

async function next() {
  if (await form.validate(steps[step.value])) step.value++;
}

const submit = form.handleSubmit((data) => api.post('/orders', data));
</script>

<template>
  <form @submit="submit">
    <template v-if="step === 0">
      <input v-model="form.values.name" name="name" />
      <input v-model="form.values.email" name="email" />
    </template>
    <!-- … -->
    <button v-if="step > 0" type="button" @click="step--">Back</button>
    <button v-if="step < steps.length - 1" type="button" @click="next">Next</button>
    <button v-else :disabled="form.submitting">Place order</button>
  </form>
</template>
  • validate(paths) 会把该步骤的字段标记为已访问(使其错误可见),如果这些字段没有错误则返回 true。
  • 路径可以指向嵌套对象或数组:validate(['address']) 会检查 address.city、address.street 等。
  • 在最后一步,handleSubmit 会校验整个表单 —— 如果用户返回修改时引入了错误,也不会被遗漏。

另请参阅 ​