Skip to content
12:13

TnForm-表单

此组件一般用于表单场景,可以配置 Input 输入框、Radio 单选框、Checkbox 多选框等,进行表单验证等。

组件位置

typescript
import TnForm from '@tuniao/tnui-vue3-uniapp/components/form/src/form.vue'
import TnFormItem from '@tuniao/tnui-vue3-uniapp/components/form/src/form-item.vue'
import TnForm from '@tuniao/tnui-vue3-uniapp/components/form/src/form.vue'
import TnFormItem from '@tuniao/tnui-vue3-uniapp/components/form/src/form-item.vue'
typescript
import TnForm from '@/uni_modules/tuniaoui-vue3/components/form/src/form.vue'
import TnFormItem from '@/uni_modules/tuniaoui-vue3/components/form/src/form-item.vue'
import TnForm from '@/uni_modules/tuniaoui-vue3/components/form/src/form.vue'
import TnFormItem from '@/uni_modules/tuniaoui-vue3/components/form/src/form-item.vue'

平台差异说明

App(vue)H5微信小程序支付宝小程序...
适配中

基本使用

此组件一般是用于表单验证使用,每一个表单域由一个TnFormItem组成,表单域中可以放置TnInputTnCheckboxTnRadioTnSwitch等。

  • 在表单中,通过 model 参数绑定一个对象,这个对象的属性名为各个TnFormItemprop属性,进行表单验证的时候,会根据prop属性,从 model 中取值进行验证。
  • TnFormItem中的各个表单组件,具体使用可以参考各个组件的文档。
vue
<script lang="ts" setup>
import { reactive, ref } from 'vue'
import TnForm from '@tuniao/tnui-vue3-uniapp/components/form/src/form.vue'
import TnFormItem from '@tuniao/tnui-vue3-uniapp/components/form/src/form-item.vue'
import TnButton from '@tuniao/tnui-vue3-uniapp/components/button/src/button.vue'
import TnInput from '@tuniao/tnui-vue3-uniapp/components/input/src/input.vue'

import type { FormRules, TnFormInstance } from '@tuniao/tnui-vue3-uniapp'

const formRef = ref<TnFormInstance>()

// 表单数据
const formData = reactive({
  username: '',
})

// 规则
const formRules: FormRules = {
  username: [
    { required: true, message: '请输入用户名', trigger: ['change', 'blur'] },
    {
      pattern: /^[\w-]{4,16}$/,
      message: '请输入4-16位英文、数字、下划线、横线',
      trigger: ['change', 'blur'],
    },
  ],
}

/* 提交表单 */
const submitForm = () => {
  formRef.value?.validate((valid) => {
    if (valid) {
      uni.showToast({
        title: '提交成功',
      })
    } else {
      uni.showToast({
        title: '表单校验失败',
        icon: 'none',
      })
    }
  })
}
</script>

<template>
  <TnForm ref="formRef" :model="formData" :rules="formRules">
    <TnFormItem label="用户名" prop="username">
      <TnInput v-model="formData.username" />
    </TnFormItem>
  </TnForm>
  <view class="tn-mt tn-flex-center">
    <TnButton size="lg" @click="submitForm"> 提交 </TnButton>
  </view>
</template>

<style lang="scss" scoped></style>
<script lang="ts" setup>
import { reactive, ref } from 'vue'
import TnForm from '@tuniao/tnui-vue3-uniapp/components/form/src/form.vue'
import TnFormItem from '@tuniao/tnui-vue3-uniapp/components/form/src/form-item.vue'
import TnButton from '@tuniao/tnui-vue3-uniapp/components/button/src/button.vue'
import TnInput from '@tuniao/tnui-vue3-uniapp/components/input/src/input.vue'

import type { FormRules, TnFormInstance } from '@tuniao/tnui-vue3-uniapp'

const formRef = ref<TnFormInstance>()

// 表单数据
const formData = reactive({
  username: '',
})

// 规则
const formRules: FormRules = {
  username: [
    { required: true, message: '请输入用户名', trigger: ['change', 'blur'] },
    {
      pattern: /^[\w-]{4,16}$/,
      message: '请输入4-16位英文、数字、下划线、横线',
      trigger: ['change', 'blur'],
    },
  ],
}

/* 提交表单 */
const submitForm = () => {
  formRef.value?.validate((valid) => {
    if (valid) {
      uni.showToast({
        title: '提交成功',
      })
    } else {
      uni.showToast({
        title: '表单校验失败',
        icon: 'none',
      })
    }
  })
}
</script>

<template>
  <TnForm ref="formRef" :model="formData" :rules="formRules">
    <TnFormItem label="用户名" prop="username">
      <TnInput v-model="formData.username" />
    </TnFormItem>
  </TnForm>
  <view class="tn-mt tn-flex-center">
    <TnButton size="lg" @click="submitForm"> 提交 </TnButton>
  </view>
</template>

<style lang="scss" scoped></style>
vue
<script lang="ts" setup>
import { reactive, ref } from 'vue'

import type { FormRules, TnFormInstance } from '@/uni_modules/tuniaoui-vue3'

const formRef = ref<TnFormInstance>()

// 表单数据
const formData = reactive({
  username: '',
})

// 规则
const formRules: FormRules = {
  username: [
    { required: true, message: '请输入用户名', trigger: ['change', 'blur'] },
    {
      pattern: /^[\w-]{4,16}$/,
      message: '请输入4-16位英文、数字、下划线、横线',
      trigger: ['change', 'blur'],
    },
  ],
}

/* 提交表单 */
const submitForm = () => {
  formRef.value?.validate((valid) => {
    if (valid) {
      uni.showToast({
        title: '提交成功',
      })
    } else {
      uni.showToast({
        title: '表单校验失败',
        icon: 'none',
      })
    }
  })
}
</script>

<template>
  <tn-form ref="formRef" :model="formData" :rules="formRules">
    <tn-form-item label="用户名" prop="username">
      <tn-input v-model="formData.username" />
    </tn-form-item>
  </tn-form>
  <view class="tn-mt tn-flex-center">
    <tn-button size="lg" @click="submitForm"> 提交 </tn-button>
  </view>
</template>

<style lang="scss" scoped></style>
<script lang="ts" setup>
import { reactive, ref } from 'vue'

import type { FormRules, TnFormInstance } from '@/uni_modules/tuniaoui-vue3'

const formRef = ref<TnFormInstance>()

// 表单数据
const formData = reactive({
  username: '',
})

// 规则
const formRules: FormRules = {
  username: [
    { required: true, message: '请输入用户名', trigger: ['change', 'blur'] },
    {
      pattern: /^[\w-]{4,16}$/,
      message: '请输入4-16位英文、数字、下划线、横线',
      trigger: ['change', 'blur'],
    },
  ],
}

/* 提交表单 */
const submitForm = () => {
  formRef.value?.validate((valid) => {
    if (valid) {
      uni.showToast({
        title: '提交成功',
      })
    } else {
      uni.showToast({
        title: '表单校验失败',
        icon: 'none',
      })
    }
  })
}
</script>

<template>
  <tn-form ref="formRef" :model="formData" :rules="formRules">
    <tn-form-item label="用户名" prop="username">
      <tn-input v-model="formData.username" />
    </tn-form-item>
  </tn-form>
  <view class="tn-mt tn-flex-center">
    <tn-button size="lg" @click="submitForm"> 提交 </tn-button>
  </view>
</template>

<style lang="scss" scoped></style>

label 对齐方式

通过设置label-position属性可以改变表单域标签的位置,默认为right,可选值为topleft, 当设为top时标签会置于表单域的顶部

vue
<TnForm label-position="top">
  <TnFormItem label="用户名" label-position="left">
    <TnInput v-model="formData.username" />
  </TnFormItem>
  <TnFormItem label="邮箱">
    <TnInput v-model="formData.email" />
  </TnFormItem>
</TnForm>
<TnForm label-position="top">
  <TnFormItem label="用户名" label-position="left">
    <TnInput v-model="formData.username" />
  </TnFormItem>
  <TnFormItem label="邮箱">
    <TnInput v-model="formData.email" />
  </TnFormItem>
</TnForm>

表单校验

TnForm组件允许你验证用户的输入是否符合规范,来帮助你找到和纠正错误。

TnForm组件提供了表单验证的功能,只需为 rules 属性传入约定的验证规则,并将 TnFormItemprop 属性设置为需要验证的特殊键值即可。 更多高级用法可参考async-validator

typescript
const rules: FormProps['rules'] = {
  username: [
    {
      required: true,
      message: '请输入用户名',
      trigger: 'blur',
    },
    {
      min: 3,
      max: 5,
      message: '长度在 3 到 5 个字符',
      trigger: 'blur',
    },
  ],
}
const rules: FormProps['rules'] = {
  username: [
    {
      required: true,
      message: '请输入用户名',
      trigger: 'blur',
    },
    {
      min: 3,
      max: 5,
      message: '长度在 3 到 5 个字符',
      trigger: 'blur',
    },
  ],
}

自定义表单验证

typescript
const validatePass = (rule: any, value: any, callback: any) => {
  if (value === '') {
    callback(new Error('请输入密码'))
  } else {
    if (formData.password !== '') {
      if (!formRef.value) return
      formRef.value.validateField('password', () => null)
    }
    callback()
  }
}
const validateRePassword = (rule: any, value: any, callback: any) => {
  if (value === '') {
    callback(new Error('请再次输入密码'))
  } else if (value !== formData.password) {
    callback(new Error('两次输入密码不一致!'))
  } else {
    callback()
  }
}

const rules: FormProps['rules'] = {
  username: [
    {
      required: true,
      message: '请输入用户名',
      trigger: 'blur',
    },
    {
      min: 3,
      max: 5,
      message: '长度在 3 到 5 个字符',
      trigger: 'blur',
    },
  ],
  password: [
    {
      validator: validatePass,
      trigger: 'blur',
    },
  ],
  rePassword: [
    {
      validator: validateRePassword,
      trigger: 'blur',
    },
  ],
}
const validatePass = (rule: any, value: any, callback: any) => {
  if (value === '') {
    callback(new Error('请输入密码'))
  } else {
    if (formData.password !== '') {
      if (!formRef.value) return
      formRef.value.validateField('password', () => null)
    }
    callback()
  }
}
const validateRePassword = (rule: any, value: any, callback: any) => {
  if (value === '') {
    callback(new Error('请再次输入密码'))
  } else if (value !== formData.password) {
    callback(new Error('两次输入密码不一致!'))
  } else {
    callback()
  }
}

const rules: FormProps['rules'] = {
  username: [
    {
      required: true,
      message: '请输入用户名',
      trigger: 'blur',
    },
    {
      min: 3,
      max: 5,
      message: '长度在 3 到 5 个字符',
      trigger: 'blur',
    },
  ],
  password: [
    {
      validator: validatePass,
      trigger: 'blur',
    },
  ],
  rePassword: [
    {
      validator: validateRePassword,
      trigger: 'blur',
    },
  ],
}

尺寸控制

表单中的所有子组件都继承了该表单的 size 属性。 同样,TnFormItem 也有一个 size 属性。

如果希望某个表单项或某个表单组件的尺寸不同于 TnForm 上的 size 属性,直接为这个表单项或表单组件设置自己的 size 属性即可。

vue
<TnForm size="sm">
  <TnFormItem label="用户名" label-position="left">
    <TnInput v-model="formData.username" />
  </TnFormItem>
  <TnFormItem label="邮箱" size="lg">
    <TnInput v-model="formData.email" />
  </TnFormItem>
</TnForm>
<TnForm size="sm">
  <TnFormItem label="用户名" label-position="left">
    <TnInput v-model="formData.username" />
  </TnFormItem>
  <TnFormItem label="邮箱" size="lg">
    <TnInput v-model="formData.email" />
  </TnFormItem>
</TnForm>

Form API

Form Props

属性名说明类型默认值可选值
model表单数据对象Object--
rules表单校验规则Object | Array--
size用于控制该表单内组件的尺寸String-smlg
disabled是否禁用该表单内的所有组件。 如果设置为 true, 它将覆盖内部组件的 disabled 属性Booleanfalsetrue
label-positionlabel 标签位置Stringrightrightlefttop
require-asterisk-position必填星号显示位置Stringleftright
hide-required-asterisk是否隐藏必填星号Booleanfalsetrue
label-widthlabel 的宽度,默认单位为 rpx,支持传入数字、带单位的数值和autoString | Number--
label-suffix表单域标签(label)的后缀String--
status-icon是否在输入框中显示校验结果反馈图标Booleanfalsetrue
show-message是否显示校验结果Booleantruefalse
validate-on-rule-change是否在校验规则修改后立马触发一次校验Booleantruefalse

Form Events

事件名说明类型
validate任一表单项被校验后触发(prop: FormItemProp, isValid: boolean, message: string) => void

Form Methods

方法名说明类型
validate对整个表单的内容进行验证。 接收一个回调函数,或返回 Promise(callback?: (isValid: boolean, invalidFields?: ValidateFieldsError) => void) => Promise<boolean>
validateField验证具体的某个字段(props?: Arrayable<FormItemProp>, callback?: (isValid: boolean, invalidFields?: ValidateFieldsError) => void) => Promise<void>
resetFields重置该表单项,将其值重置为初始值,并移除校验结果(props?: Arrayable<FormItemProp>) => void
clearValidate清理某个字段的表单验证信息(props?: Arrayable<FormItemProp>) => void

Form Slots

插槽名说明子标签
default自定义内容TnFormItem

FormItem API

FormItem Props

属性名说明类型默认值可选值
labellabel 文本String--
label-widthlabel 的宽度,默认单位为 rpx,支持传入数字、带单位的数值和autoString | Number--
label-positionlabel 标签位置Stringrightrightlefttop
propmodel 的键名。 它可以是一个路径数组(例如 ['userInfo', 'hobby', 0])。 在定义了 validateresetFields 的方法时,该属性是必填的String | Array<String>--
required是否为必填项,如不设置,则会根据校验规则确认Booleanfalsetrue
rules表单校验规则Object | Array--
error表单域验证错误时的提示信息。设置该值会导致表单验证状态变为 error,并显示该错误信息。String--
validate-status校验状态FormItemValidateStates--
show-message是否显示校验结果Booleantruefalse
size用于控制该表单内组件的尺寸String-smlg

FormItem Methods

方法名说明类型
validate验证表单项(callback?: FormValidateCallback) => FormValidationResult
resetFields对该表单项进行重置,将其值重置为初始值并移除校验结果() => void
clearValidate移除该表单项的校验结果() => void

FormItem Exposes

名称说明类型
size表单项尺寸大小ComputedRef<'' | 'sm' | 'lg'>
validateMessage校验消息Ref<string>
validateState校验状态Ref<'' | 'error' | 'validating' | 'success'>

FormItem Slots

插槽名说明
default自定义表单内容
label标签位置显示的内容

Tuniao UI