条件渲染
根据表单状态动态显示或隐藏字段,创建智能响应式表单。
概述
AutoForm 的 meta 字段均可传入响应式函数 (ctx) => value,ctx 为 AutoFormFieldContext(含 state、path、value)。函数会随表单状态自动重算,从而实现条件渲染与字段联动。
条件渲染有两种方式,行为不同:
if- 显示条件,结果为false时字段不会创建(不挂载、不参与校验)。hidden- 是否隐藏,结果为true时字段仍保留在 DOM 与表单数据中,只是视觉隐藏。
示例
条件渲染
if 与 hidden 接收返回布尔值的函数:切换账户类型时,企业字段(if)按需挂载/卸载;勾选条款后,订阅字段(hidden)从隐藏切换为显示。
需要彻底排除字段(不校验、不提交)用
if;只想临时隐藏但保留取值用 hidden。<script lang="ts" setup>
import type { FormSubmitEvent } from '@nuxt/ui'
import type { z } from 'zod'
import type { AutoFormFieldContext } from '@movk/nuxt'
const { afz } = useAutoForm()
const toast = useToast()
const schema = afz.object({
accountType: afz
.enum(['personal', 'business'])
.default('personal')
.meta({ label: '账户类型', description: '切换后观察 company/tax 字段的挂载与卸载' }),
username: afz
.string({ controlProps: { placeholder: '请输入用户名' } })
.min(3, '用户名至少需要 3 个字符')
.meta({ label: '用户名' }),
companyName: afz
.string({ controlProps: { placeholder: '请输入公司名称' } })
.meta({
label: '公司名称(if)',
hint: 'if:仅企业账户挂载,个人账户下字段不创建、不参与校验',
if: ({ state }: AutoFormFieldContext) => state?.accountType === 'business'
}),
taxId: afz
.string({ controlProps: { placeholder: '请输入税号' } })
.meta({
label: '税号(if)',
hint: 'if:与公司名称同条件挂载',
if: ({ state }: AutoFormFieldContext) => state?.accountType === 'business'
}),
agreeToTerms: afz
.boolean()
.default(false)
.meta({ label: '同意服务条款', description: '勾选后下方订阅字段显示' }),
newsletter: afz
.boolean()
.default(true)
.meta({
label: '订阅邮件通知(hidden)',
description: 'hidden:未同意条款时隐藏,但字段始终保留在 DOM 与表单数据中',
hidden: ({ state }: AutoFormFieldContext) => !state?.agreeToTerms
})
})
type Schema = z.output<typeof schema>
const form = ref<Partial<Schema>>({})
async function onSubmit(event: FormSubmitEvent<Schema>) {
toast.add({
title: '提交成功',
color: 'success',
description: JSON.stringify(event.data, null, 2)
})
}
</script>
<template>
<MAutoForm :schema="schema" :state="form" @submit="onSubmit" />
</template>
依赖联动
函数式 controlProps 随其它字段变化重算控件属性。下例中城市选项依赖国家字段,并通过 watch 在国家变化时清空已失效的旧值。
联动仅重算控件属性,不会自动清除旧值。需要清空失效选项时,配合
watch 手动重置。<script lang="ts" setup>
import type { z } from 'zod'
const { afz } = useAutoForm()
const countryOptions = ['CN', 'US', 'JP'] as const
type CountryCode = typeof countryOptions[number]
const cityItemsByCountry: Record<CountryCode, string[]> = {
CN: ['北京', '上海', '广州'],
US: ['New York', 'San Francisco', 'Seattle'],
JP: ['Tokyo', 'Osaka', 'Kyoto']
}
const schema = afz.object({
country: afz.enum(countryOptions).default('CN').meta({ label: '国家' }),
city: afz.enum([], {
type: 'enum',
controlProps: ({ state }) => ({
items: cityItemsByCountry[(state.country as CountryCode | undefined) ?? 'CN']
})
}).meta({ label: '城市', hint: '选项随国家变化,切换国家后会清空已选城市' })
})
const state = reactive<Partial<z.output<typeof schema>>>({})
watch(() => state.country, () => {
state.city = undefined
})
</script>
<template>
<MAutoForm :schema="schema" :state="state" />
</template>
API
meta
| Name | Type | Description |
|---|---|---|
if | ReactiveValue<boolean, AutoFormFieldContext> | 显示条件,false 时字段不创建 |
hidden | ReactiveValue<boolean, AutoFormFieldContext> | 是否隐藏,true 时保留 DOM 但视觉隐藏 |
除上述字段外,
label、hint、description、controlProps、class 等 meta 字段同样支持 (ctx) => value 函数形态,按表单状态动态求值。