---
title: "String 字符串"
description: "afz.string() 到各类输入控件的映射与配置。"
seo_title: "String Field"
seo_description: "How a Zod string field maps to AutoForm controls — input, textarea, password toggle, clear, copy, character limit, phone mask, floating label, pin input, input menu and color chooser."
canonical_url: "https://nuxt.mhaibaraai.cn/docs/auto-form/string"
---
# String 字符串

> afz.string() 到各类输入控件的映射与配置。

> \[\!NOTE\]
> See: https://zod.dev/api#strings
> 
> 使用 
> 
> afz.string()
> 
>  创建字符串字段：

## `Input`

> \[\!NOTE\]
> See: https://ui.nuxt.com/docs/components/input
> 
> Input 组件文档

基础输入框，通过 `controlProps` 配置图标、颜色等属性：

```vue [AutoFormFieldStringInputExample.vue]
<script lang="ts" setup>
import type { FormSubmitEvent } from '@nuxt/ui'
import type { z } from 'zod'

const { afz } = useAutoForm()
const toast = useToast()

const schema = afz.object({
  text: afz.string({
    controlProps: {
      icon: 'i-lucide-text'
    }
  })
    .min(3, '至少 3 个字符')
    .max(20, '最多 20 个字符')
    .meta({
      label: '基础输入框',
      placeholder: '请输入文本',
      hint: '支持图标、颜色等配置'
    })
})

async function onSubmit(event: FormSubmitEvent<z.output<typeof schema>>) {
  toast.add({
    title: 'Success',
    color: 'success',
    description: JSON.stringify(event.data, null, 2)
  })
}
</script>

<template>
  <MAutoForm :schema="schema" @submit="onSubmit" />
</template>
```

## `Textarea`

> \[\!NOTE\]
> See: https://ui.nuxt.com/docs/components/textarea
> 
> Textarea 组件文档

多行文本输入，设置 `type: 'textarea'`，支持自动调整高度：

```vue [AutoFormFieldStringTextareaExample.vue]
<script lang="ts" setup>
import type { FormSubmitEvent } from '@nuxt/ui'
import type { z } from 'zod'

const { afz } = useAutoForm()
const toast = useToast()

const schema = afz.object({
  description: afz.string({
    type: 'textarea',
    controlProps: {
      maxrows: 2,
      autoresize: true
    }
  })
    .min(10, '至少 10 个字符')
    .meta({
      label: '文本域',
      placeholder: '请输入多行文本...',
      hint: '这是一个长文本,将自动调整高度,最多 2 行。'
    })
})

async function onSubmit(event: FormSubmitEvent<z.output<typeof schema>>) {
  toast.add({
    title: 'Success',
    color: 'success',
    description: JSON.stringify(event.data, null, 2)
  })
}
</script>

<template>
  <MAutoForm :schema="schema" @submit="onSubmit" />
</template>
```

## `WithClear`

输入内容后显示清除按钮，设置 [`type: 'withClear'`](/docs/components/with-clear):

```vue [AutoFormFieldStringWithClearExample.vue]
<script lang="ts" setup>
import type { FormSubmitEvent } from '@nuxt/ui'
import type { z } from 'zod'

const { afz } = useAutoForm()
const toast = useToast()

const schema = afz.object({
  search: afz.string({
    type: 'withClear',
    controlProps: {
      icon: 'i-lucide-search'
    }
  })
    .meta({
      label: '带清除按钮',
      placeholder: '输入内容后显示清除按钮',
      hint: '点击清除图标快速清空内容'
    })
})

async function onSubmit(event: FormSubmitEvent<z.output<typeof schema>>) {
  toast.add({
    title: 'Success',
    color: 'success',
    description: JSON.stringify(event.data, null, 2)
  })
}
</script>

<template>
  <MAutoForm :schema="schema" @submit="onSubmit" />
</template>
```

## `WithPasswordToggle`

密码输入框，可切换显示/隐藏，设置 [`type: 'withPasswordToggle'`](/docs/components/with-password-toggle):

```vue [AutoFormFieldStringWithPasswordToggleExample.vue]
<script lang="ts" setup>
import type { FormSubmitEvent } from '@nuxt/ui'
import type { z } from 'zod'

const { afz } = useAutoForm()
const toast = useToast()

const schema = afz.object({
  password: afz.string({
    type: 'withPasswordToggle'
  })
    .min(8, '密码至少 8 个字符')
    .meta({
      label: '密码切换',
      placeholder: '请输入密码',
      hint: '点击眼睛图标切换显示/隐藏'
    })
})

async function onSubmit(event: FormSubmitEvent<z.output<typeof schema>>) {
  toast.add({
    title: 'Success',
    color: 'success',
    description: JSON.stringify(event.data, null, 2)
  })
}
</script>

<template>
  <MAutoForm :schema="schema" @submit="onSubmit" />
</template>
```

## `WithCopy`

点击复制按钮快速复制内容，设置 [`type: 'withCopy'`](/docs/components/with-copy):

```vue [AutoFormFieldStringWithCopyExample.vue]
<script lang="ts" setup>
import type { FormSubmitEvent } from '@nuxt/ui'
import type { z } from 'zod'

const { afz } = useAutoForm()
const toast = useToast()

const schema = afz.object({
  apiKey: afz.string({
    type: 'withCopy'
  })
    .meta({
      label: '带复制按钮',
      placeholder: '输入内容后可复制',
      hint: '点击复制图标快速复制到剪贴板'
    })
})

async function onSubmit(event: FormSubmitEvent<z.output<typeof schema>>) {
  toast.add({
    title: 'Success',
    color: 'success',
    description: JSON.stringify(event.data, null, 2)
  })
}
</script>

<template>
  <MAutoForm :schema="schema" @submit="onSubmit" />
</template>
```

## `WithCharacterLimit`

实时显示剩余字符数，设置 [`type: 'withCharacterLimit'`](/docs/components/with-character-limit):

```vue [AutoFormFieldStringWithCharacterLimitExample.vue]
<script lang="ts" setup>
import type { FormSubmitEvent } from '@nuxt/ui'
import type { z } from 'zod'

const { afz } = useAutoForm()
const toast = useToast()

const schema = afz.object({
  title: afz.string({
    type: 'withCharacterLimit',
    controlProps: {
      maxlength: 50
    }
  })
    .max(50, '最多 50 个字符')
    .meta({
      label: '字符限制',
      placeholder: '请输入标题',
      hint: '实时显示剩余字符数'
    })
})

async function onSubmit(event: FormSubmitEvent<z.output<typeof schema>>) {
  toast.add({
    title: 'Success',
    color: 'success',
    description: JSON.stringify(event.data, null, 2)
  })
}
</script>

<template>
  <MAutoForm :schema="schema" @submit="onSubmit" />
</template>
```

## `AsPhoneNumberInput`

电话号码输入增强组件，支持掩码格式化和区号前缀，设置 [`type: 'asPhoneNumberInput'`](/docs/components/as-phone-number-input):

```vue [AutoFormFieldStringAsPhoneNumberInputExample.vue]
<script lang="ts" setup>
import type { FormSubmitEvent } from '@nuxt/ui'
import type { z } from 'zod'

const { afz } = useAutoForm()
const toast = useToast()

const schema = afz.object({
  phone: afz.string({
    type: 'asPhoneNumberInput',
    controlProps: {
      dialCode: '+86',
      mask: '### #### ####'
    }
  })
    .meta({
      label: '手机号',
      placeholder: '请输入手机号',
      hint: '自动按手机号格式输入'
    })
})

async function onSubmit(event: FormSubmitEvent<z.output<typeof schema>>) {
  toast.add({
    title: 'Success',
    color: 'success',
    description: JSON.stringify(event.data, null, 2)
  })
}
</script>

<template>
  <MAutoForm :schema="schema" @submit="onSubmit" />
</template>
```

## `WithFloatingLabel`

浮动标签输入框，聚焦或有内容时标签上浮，设置 [`type: 'withFloatingLabel'`](/docs/components/with-floating-label):

```vue [AutoFormFieldStringWithFloatingLabelExample.vue]
<script lang="ts" setup>
import type { FormSubmitEvent } from '@nuxt/ui'
import type { z } from 'zod'

const { afz } = useAutoForm()
const toast = useToast()

const schema = afz.object({
  email: afz.string({
    type: 'withFloatingLabel',
    controlProps: {
      label: '邮箱地址',
      leadingIcon: 'i-lucide-mail',
      type: 'email'
    }
  })
    .meta({
      label: '',
      hint: '标签会在输入时自动上浮'
    }).optional()
})

async function onSubmit(event: FormSubmitEvent<z.output<typeof schema>>) {
  toast.add({
    title: 'Success',
    color: 'success',
    description: JSON.stringify(event.data, null, 2)
  })
}
</script>

<template>
  <MAutoForm :schema="schema" @submit="onSubmit" />
</template>
```

## `PinInput`

> \[\!NOTE\]
> See: https://ui.nuxt.com/docs/components/pin-input
> 
> PinInput 组件文档

验证码或 PIN 码输入，设置 `type: 'pinInput'`:

```vue [AutoFormFieldStringPinInputExample.vue]
<script lang="ts" setup>
import type { FormSubmitEvent } from '@nuxt/ui'
import type { z } from 'zod'

const { afz } = useAutoForm()
const toast = useToast()

const schema = afz.object({
  code: afz.string({
    type: 'pinInput',
    controlProps: {
      length: 6,
      mask: false
    }
  })
    .length(6, '请输入 6 位验证码')
    .meta({
      label: '验证码输入',
      hint: '输入 6 位验证码'
    })
})

async function onSubmit(event: FormSubmitEvent<z.output<typeof schema>>) {
  toast.add({
    title: 'Success',
    color: 'success',
    description: JSON.stringify(event.data, null, 2)
  })
}
</script>

<template>
  <MAutoForm :schema="schema" @submit="onSubmit" />
</template>
```

## `InputMenu`

> \[\!NOTE\]
> See: https://ui.nuxt.com/docs/components/input-menu
> 
> InputMenu 组件文档

支持输入和下拉选择，设置 `type: 'inputMenu'`:

```vue [AutoFormFieldStringInputMenuExample.vue]
<script lang="ts" setup>
import type { FormSubmitEvent, InputMenuItem } from '@nuxt/ui'
import type { z } from 'zod'

const { afz } = useAutoForm()
const toast = useToast()

const items = [
  { label: 'Apple', value: 'apple' },
  { label: 'Banana', value: 'banana' },
  { label: 'Orange', value: 'orange' },
  { label: 'Grape', value: 'grape' }
] satisfies InputMenuItem[]

const schema = afz.object({
  fruit: afz.string({
    type: 'inputMenu',
    controlProps: {
      items,
      valueKey: 'value'
    }
  })
    .meta({
      label: '输入菜单',
      placeholder: '输入或选择水果',
      hint: '支持输入和下拉选择'
    })
})

async function onSubmit(event: FormSubmitEvent<z.output<typeof schema>>) {
  toast.add({
    title: 'Success',
    color: 'success',
    description: JSON.stringify(event.data, null, 2)
  })
}
</script>

<template>
  <MAutoForm :schema="schema" @submit="onSubmit" />
</template>
```

## `ColorChooser`

颜色选择器，支持可视化颜色选择和格式化，设置 [`type: 'colorChooser'`](/docs/components/color-chooser)：

```vue [AutoFormFieldStringColorChooserExample.vue]
<script lang="ts" setup>
import type { FormSubmitEvent } from '@nuxt/ui'
import type { z } from 'zod'

const { afz } = useAutoForm()
const toast = useToast()

const schema = afz.object({
  color: afz.string({
    type: 'colorChooser',
    controlProps: {
      format: 'rgb'
    }
  })
    .meta({
      label: '颜色选择器',
      placeholder: '选择颜色'
    })
})

async function onSubmit(event: FormSubmitEvent<z.output<typeof schema>>) {
  toast.add({
    title: 'Success',
    color: 'success',
    description: JSON.stringify(event.data, null, 2)
  })
}
</script>

<template>
  <MAutoForm :schema="schema" @submit="onSubmit" />
</template>
```

## 动态类型

通过交互式示例探索字符串字段的各种类型和配置选项，包括：普通输入框、文本域、密码切换、清除按钮、复制功能、字符限制、手机号掩码输入、浮动标签输入等增强功能，以及尺寸、颜色、行数等样式配置。

```vue [AutoFormFieldStringTypeExample.vue]
<script lang="ts" setup>
import type { FormSubmitEvent } from '@nuxt/ui'
import type z from 'zod'

const props = defineProps<{
  type: 'string' | 'textarea' | 'withPasswordToggle' | 'withClear' | 'withCopy' | 'withCharacterLimit' | 'asPhoneNumberInput' | 'withFloatingLabel'
  size: 'sm' | 'xs' | 'md' | 'lg' | 'xl'
  color: 'error' | 'primary' | 'secondary' | 'success' | 'info' | 'warning' | 'neutral'
  rows?: number
  maxLength?: number
}>()

const { afz } = useAutoForm()
const toast = useToast()

const resolvedControlProps = computed(() => ({
  leadingIcon: props.type === 'withFloatingLabel' ? undefined : 'i-lucide-type',
  color: props.color,
  rows: props.rows,
  maxLength: props.maxLength,
  label: props.type === 'withFloatingLabel' ? '浮动标签' : undefined,
  dialCode: props.type === 'asPhoneNumberInput' ? '+86' : undefined,
  mask: props.type === 'asPhoneNumberInput' ? '### #### ####' : undefined
}))

const schema = computed(() => (afz.object({
  stringWithType: afz.string({
    type: props.type,
    controlProps: resolvedControlProps.value
  }).meta({
    size: props.size,
    label: props.type === 'withFloatingLabel' ? '' : undefined
  }).optional()
})))

type Schema = z.output<typeof schema.value>

const form = ref<Partial<Schema>>({})

async function onSubmit(event: FormSubmitEvent<Schema>) {
  toast.add({
    title: 'Success',
    color: 'success',
    description: JSON.stringify(event.data, null, 2)
  })
}
</script>

<template>
  <UCard class="w-lg">
    <MAutoForm
      :schema="schema"
      :state="form"
      :submit-button-props="{
        color
      }"
      @submit="onSubmit"
    />
  </UCard>
</template>
```


## Sitemap

See the full [sitemap](/sitemap.md) for all pages.
