条件渲染

View source
根据表单状态动态显示或隐藏字段,创建智能响应式表单。

概述

AutoForm 的 meta 字段均可传入响应式函数 (ctx) => valuectxAutoFormFieldContext(含 statepathvalue)。函数会随表单状态自动重算,从而实现条件渲染与字段联动。

条件渲染有两种方式,行为不同:
  • if - 显示条件,结果为 false 时字段不会创建(不挂载、不参与校验)。
  • hidden - 是否隐藏,结果为 true 时字段仍保留在 DOM 与表单数据中,只是视觉隐藏。

示例

条件渲染

ifhidden 接收返回布尔值的函数:切换账户类型时,企业字段(if)按需挂载/卸载;勾选条款后,订阅字段(hidden)从隐藏切换为显示。

需要彻底排除字段(不校验、不提交)用 if;只想临时隐藏但保留取值用 hidden

切换后观察 company/tax 字段的挂载与卸载

勾选后下方订阅字段显示

<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

NameTypeDescription
ifReactiveValue<boolean, AutoFormFieldContext>显示条件,false 时字段不创建
hiddenReactiveValue<boolean, AutoFormFieldContext>是否隐藏,true 时保留 DOM 但视觉隐藏
除上述字段外,labelhintdescriptioncontrolPropsclass 等 meta 字段同样支持 (ctx) => value 函数形态,按表单状态动态求值。
Copyright © 2025 - 2026 YiXuan - MIT License