Skip to content

XForm 表单组件

介绍

此表单组件和 VantForm 组件 不同,XForm 收集了 Vant 的各类表单组件以及自定义组件,目前支持 20种组件,这些组件覆盖了90%日常业务功能;开发者只需要通过简单的配置即可完成日常业务的开发。

引入

这里只展示局部引入使用,如需要全局引入,请参考 全局引入

vue
<template>
  <XForm :model="form" :items="formOption" />
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { XForm,type XFormItemRow } from 'vant4-kit'

const form = ref()
const formOption=ref<XFormItemRow[]>(
    {
        type:'input',
        name:'name',
        label:'姓名',
    }
)
</script>

代码演示

基础用法

<template>
  <div>
    <x-form :model="formValue" :items="formOptions" label-align="top">
      <template #customSlot1>
        <h3>我是一个自定义 field input插槽</h3>
      </template>
      <template #customSlot>
        <Button type="primary" block>我也是插槽,但我是一个不带field的插槽</Button>
      </template>
    </x-form>
  </div>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { Button } from 'vant'
import type { XFormItemOption } from 'vant4-kit';
const formValue = ref({
  text: '我是一段自定义文本',
  html: '<h4>我是一个带h4标签的html片段</h4>'
})
const formOptions = ref<XFormItemOption>([
  {
    label: '普通输入',
    type: 'input',
    name: 'name',
  },
  {
    label: '手机号',
    type: 'input',
    name: 'tel',
    itemProps: {
      type: 'tel',
    }
  },
  {
    label: '纯数字(可以带小数)',
    type: 'input',
    name: 'number',
    itemProps: {
      type: 'number',
    }
  },
  {
    label: '整数',
    type: 'input',
    name: 'digit',
    itemProps: {
      type: 'digit',
    }
  },
  {
    label: '密码输入',
    type: 'input',
    name: 'password',
    itemProps: {
      type: 'password',
    }
  },
  {
    label: '文本域',
    type: 'input',
    name: 'textarea',
    itemProps: {
      type: 'textarea',
      row: 2,
      autosize: true,
      'show-word-limit': true,
      maxlength: 50,
    }
  },
  {
    label: '步进器',
    type: 'stepper',
    name: 'age',

  },
  {
    label: '单选',
    type: 'radio',
    name: 'sex',
    options: [
      { text: '男', value: '1' },
      { text: '女', value: '0' },

    ]
  },
  {
    label: '多选',
    type: 'checkbox',
    name: 'checkbox',
    options: [
      { text: '男', value: '1', attrs: { disabled: true } },
      { text: '女', value: '0' },
      { text: '未知', value: '2' },
    ],
    attrs: {
      shape: 'square',
    }
  },
  {
    label: '滑动',
    type: 'slider',
    name: 'slider',
  },
  {
    label: '开关',
    type: 'switch',
    name: 'switch',
    attrs: {
      activeValue: '1',
      inactiveValue: '0'
    }
  },
  {
    type: 'rate',
    label: 'rate 评分',
    name: 'rate',
    attrs: {
      count: 6
    },
  },

  {
    label: '选择器(多列)',
    type: 'picker',
    name: 'hubby',
    options: [
      {
        text: '浙江',
        value: 'Zhejiang',
        children: [
          {
            text: '杭州',
            value: 'Hangzhou',
            children: [
              { text: '西湖区', value: 'Xihu' },
              { text: '余杭区', value: 'Yuhang' },
            ],
          },
          {
            text: '温州',
            value: 'Wenzhou',
            children: [
              { text: '鹿城区', value: 'Lucheng' },
              { text: '瓯海区', value: 'Ouhai' },
            ],
          },
        ],
      },
      {
        text: '福建',
        value: 'Fujian',
        children: [
          {
            text: '福州',
            value: 'Fuzhou',
            children: [
              { text: '鼓楼区', value: 'Gulou' },
              { text: '台江区', value: 'Taijiang' },
            ],
          },
          {
            text: '厦门',
            value: 'Xiamen',
            children: [
              { text: '思明区', value: 'Siming' },
              { text: '海沧区', value: 'Haicang' },
            ],
          },
        ],
      },
    ]
  },
  {
    label: '选择器(单列)',
    type: 'picker',
    name: 'picker1',
    options: [
      { text: '杭州', value: 'Hangzhou' },
      { text: '宁波', value: 'Ningbo' },
      { text: '温州', value: 'Wenzhou' },
      { text: '绍兴', value: 'Shaoxing' },
      { text: '湖州', value: 'Huzhou' },
    ],
  },
  {
    type: 'date-picker',
    label: '日期',
    name: 'datePicker',
    attrs: {
      // 'columns-type': ['year']
    }
  },
  {
    type: 'date-picker',
    label: '日期(年份)',
    name: 'datePicker2',
    attrs: {
      'columns-type': ['year']
    },
  },
  {
    type: 'time-picker',
    label: '时间选择',
    name: 'timePicker',
    attrs: {
    }
  },
  {
    type: 'datetime-picker',
    label: '日期时间(单页)',
    name: 'datetimePicker',
    attrs: {
      showType: 'single',
      groupProps: {
        'columns-type': ['hour', 'minute']
      }

    }
  },
  {
    type: 'datetime-picker',
    label: '日期时间(组合)',
    name: 'datetimePicker1',
    attrs: {
      showType: 'group',
      groupProps: [
        { 'columns-type': ['year', 'month', 'day'] },
        { 'columns-type': ['hour', 'minute', 'second'] }
      ]
    }
  },
  {
    type: 'date-range-picker',
    label: '日期范围',
    name: 'dateRangePicker',
    attrs: {
    }
  },
  {
    type: 'time-range-picker',
    label: '时间范围',
    name: 'timeRangePicker',
    attrs: {
    }
  },
  {
    type: 'datetime-range-picker',
    label: '日期时间范围',
    name: 'datetimeRangePicker',
    attrs: {
      groupProps: [
        { 'columns-type': ['hour', 'minute',] },
        { 'columns-type': ['hour', 'minute', 'second'] }
      ]
    }
  },
  {
    type: 'area',
    label: '地区',
    name: 'areaPicker',
    attrs: {
    }
  },
  {
    type: 'cascader',
    label: '级联',
    name: 'cascader',
    attrs: {
      useVantAreaData: true
    }
  },
  {
    type: 'text',
    label: '文本',
    name: 'text',
  },
  {
    type: 'html',
    label: 'html片段',
    name: 'html',
    hiddenLabel: false
  },
  {
    type: 'input-slot',
    label: '表单插槽',
    name: 'customSlot1',
  },
  {
    type: 'slot',
    label: '全部插槽',
    name: 'customSlot',
  },
])
</script>
<style scoped></style>
基本表单

对其方式

<template>
    <x-form :model="formValue" :items="formOptions" :label-align="formValue.labelAlign"
        :input-align="formValue.inputAlign">
    </x-form>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import type { XFormItemOption } from 'vant4-kit';
const formValue = ref({
    labelAlign: 'left',
    inputAlign: 'left',
})
const formOptions = ref<XFormItemOption>([
    {
        label: 'label对其方式',
        type: 'radio',
        name: 'labelAlign',
        options: [
            { text: '左对齐', value: 'left' },
            { text: '右对齐', value: 'right' },
            { text: '顶部对其', value: 'top' },
            { text: '居中对齐', value: 'center' },
        ]
    },
    {
        label: 'Input对其方式',
        type: 'radio',
        name: 'inputAlign',
        options: [
            { text: '左对齐', value: 'left' },
            { text: '居中对齐', value: 'center' },
            { text: '右对齐', value: 'right' },
        ]
    },
    {
        label: '普通输入',
        type: 'input',
        name: 'name',
    },
    {
        label: '手机号',
        type: 'input',
        name: 'tel',
        itemProps: {
            type: 'tel',
        }
    },
    {
        label: '文本域',
        type: 'input',
        name: 'textarea',
        itemProps: {
            type: 'textarea',
            row: 2,
            autosize: true,
            'show-word-limit': true,
            maxlength: 50,
        }
    },
    {
        label: '步进器',
        type: 'stepper',
        name: 'age',
    },
    {
        type: 'rate',
        label: 'rate 评分',
        name: 'rate',
        attrs: {
            count: 6
        },
    },
    {
        type: 'date-picker',
        label: '日期',
        name: 'datePicker',
        attrs: {
        }
    },
    {
        type: 'time-picker',
        label: '时间选择',
        name: 'timePicker',
        attrs: {
        }
    },
    {
        type: 'date-range-picker',
        label: '日期范围',
        name: 'dateRangePicker',
        attrs: {
        }
    },
    {
        type: 'time-range-picker',
        label: '时间范围',
        name: 'timeRangePicker',
        attrs: {
        }
    },
    {
        type: 'datetime-range-picker',
        label: '日期时间范围',
        name: 'datetimeRangePicker',
        attrs: {
            groupProps: [
                { 'columns-type': ['hour', 'minute',] },
                { 'columns-type': ['hour', 'minute', 'second'] }
            ]
        }
    },
])
</script>
<style lang="scss" scoped></style>
对齐方式

校验表单

校验表单有多种配置方式,

  • 通过 XFormrequired 参数快捷配置全部表单项必填
<template>
    <x-form  ref="formRef" :model="formValue" :items="formItems" required >
        
    </x-form>
    <div >
      <Button type="primary" @click="onSubmit" block>提交</Button>
    </div>
  </template>
  
  <script lang="ts" setup>
  import type {FormInstance,FieldRule} from 'vant'
  import  { Button,showFailToast } from 'vant'
  import type { XFormItemOption } from 'vant4-kit';
  import { ref, h } from 'vue'
  
  const formRef=ref<FormInstance>()
  const formValue = ref({})
  const formItems = ref<XFormItemOption>([
    {
      type: 'input',
      label: '账号',
      name:'name'
    },
    {
      type: 'input',
      label: '密码',
      name:'pasword',
      attrs:{
        type:'password',
      }
    },
    
  ])

  const onSubmit=()=>{
    formRef.value?.validate().then(()=>{
      console.log('submit values =',formValue.value);
    }).catch(error=>{
      console.log('error',error);
      showFailToast('请检查表单填写')
    })
  }
  </script>
  <style lang="scss" scoped>
  </style>
校验表单
  • 通过在 XFormrules 参数来配置表单项的自定义校验
<template>
  <x-form  ref="formRef" :model="formValue" :items="formItems" :rules="formRules" >
   </x-form>
  <div >
    <Button type="primary" @click="onSubmit" block>提交</Button>
  </div>
</template>

<script lang="ts" setup>
import type {FormInstance,FieldRule} from 'vant'
import  { Button,showFailToast } from 'vant'
import type { XFormItemOption } from 'vant4-kit';
import { ref, h } from 'vue'

const formRef=ref<FormInstance>()
const formValue = ref({})
const formItems = ref<XFormItemOption>([
  {
    type: 'input',
    label: '姓名',
    name:'name'
  },
  {
    type: 'input',
    label: '手机号',
    name:'tel',
    attrs:{
      type:'tel',
    }
  },
  {
    type: 'input',
    label: '邮箱',
    name:'email',
  },
])

const formRules:{ [key:string]:FieldRule[] }={
  name:[
    { required:true,message:'请输入姓名',trigger:['onBlur']}
  ],
  tel:[
    { required:true,message:'请输入手机号',trigger:['onBlur']},
    { pattern: /^1[3456789]\d{9}$/, message: '请输入正确的手机号', trigger: ['onChange','onBlur'] },
  ],
  email:[
    { required:true,message:'请输入邮箱',trigger:['onBlur',]},
    { pattern: /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/, message: '请输入正确的邮箱', trigger: ['onChange','onBlur'] },
  ]
}

const onSubmit=()=>{
  formRef.value?.validate().then(()=>{
    console.log('submit values =',formValue.value);
  }).catch(error=>{
    console.log('error',error);
    showFailToast('请检查表单填写')
  })
}
</script>
<style lang="scss" scoped>
</style>
校验表单
  • 通过在 XForm 组件的 items 的参数配置对象中配置 required ,实现当前表单的必填校验,或在参数中配置 rules 来实现当前表单项的自定义校验规则
<template>
  <x-form ref="formRef" :model="formValue" :items="formItems"></x-form>
  <div>
    <Button type="primary" @click="onSubmit" block>提交</Button>
  </div>
</template>

<script lang="ts" setup>
import type { FormInstance, FieldRule } from 'vant'
import { Button, showFailToast } from 'vant'
import type { XFormItemOption } from 'vant4-kit';
import { ref, h } from 'vue'

const formRef = ref<FormInstance>()
const formValue = ref({})
const formItems = ref<XFormItemOption>([
  {
    type: 'input',
    label: '姓名',
    name: 'name',
    required: true,
  },
  {
    type: 'input',
    label: '邮箱',
    required: true,
    name: 'email',
    itemProps: {
      rules: [
        { pattern: /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/, message: '请输入正确的邮箱', trigger: ['onChange', 'onBlur'] },
      ],
    }

  },
  {
    type: 'checkbox',
    label: '兴趣',
    name: 'hobby',
    required: true,
    options: [
      { text: '篮球', value: 'basketball' },
      { text: '足球', value: 'football' },
      { text: '羽毛球', value: 'badminton' },
    ],
    attrs: {
      shape: 'square'
    }
  }
])

const onSubmit = () => {
  formRef.value?.validate().then(() => {
    console.log('submit values =', formValue.value);
  }).catch(error => {
    console.log('error', error);
    showFailToast('请检查表单填写')
  })
}
</script>
<style lang="scss" scoped></style>
校验表单

插槽用法

插槽用法分为两种,一种是在 XForm 组件上直接使用插槽,另外一种是直接在itemProps 通过配置 slots 属性下的插槽渲染函数来实现自定义渲染

组件插槽方式

<template>
    <x-form :model="formValue" :items="formItems">
        <template #labelSlot.label>
            <span style="color:red">我是label插槽</span>
        </template>
        <template #leftIconSlot.left-icon>
            <Icon name="smile" />
        </template>
        <template #rightIconSlot.right-icon>
            <Icon name="fire-o" color="#ee0a24" />
        </template>
        <template #errorMessage.error-message="{ message }">
            <span>错误提示插槽:{{ message }}</span>
        </template>
        <template #button.button>
            <Button type="primary" size="small">尾部按钮</Button>
        </template>
        <template #extra.extra>
            <span>额外内容</span>
        </template>
        <template #customSlot>
            <h3>自定义表单项输入区插槽</h3>
        </template>
        <template #solt>
            <h3>自定义表单项插槽</h3>
        </template>
    </x-form>
</template>

<script lang="ts" setup>
import type { XFormItemOption } from 'vant4-kit';
import { ref } from 'vue'
import { Icon, Button } from 'vant';

const formValue = ref({})
const formItems = ref<XFormItemOption>([
    {
        type: 'input',
        label: 'Label 插槽',
        name: 'labelSlot'
    },
    {
        type: 'input',
        label: '左图标插槽',
        name: 'leftIconSlot'
    },
    {
        type: 'input',
        label: '有图标插槽',
        name: 'rightIconSlot'
    },
    {
        type: 'input',
        label: '按钮插槽',
        name: 'button'
    },
    {
        type: 'input',
        label: '错误提示插槽',
        name: 'errorMessage',
        itemProps: {
            'errorMessage': '我错啦'
        }
    },
    {
        type: 'input',
        label: '额外内容插槽',
        name: 'extra'
    },
    {
        type: 'input-slot',
        label: '自定义插槽',
        name: 'customSlot'
    },
    {
        type: 'slot',
        label: '输入框',
        name: 'solt'
    }
])
</script>
<style lang="scss" scoped></style>
自定义插槽

插槽函数

<template>
    <x-form :model="formValue" :items="formItems">
    </x-form>
</template>

<script lang="ts" setup>
import type { XFormItemOption } from 'vant4-kit';
import { ref, h } from 'vue'
import { Icon, Button } from 'vant';

const formValue = ref({})
const formItems = ref<XFormItemOption>([
    {
        type: 'input',
        label: 'Label 插槽',
        name: 'labelSlot',
        itemProps: {
            slots: {
                label: () => h('span', { style: { color: 'red' } }, '我是label插槽')
            }
        }
    },
    {
        type: 'input',
        label: '图标插槽',
        name: 'leftIconSlot',
        itemProps: {
            slots: {
                'left-icon': () => h(Icon, { name: 'smile' }),
                'right-icon': () => h(Icon, { name: 'fire-o', color: '#ee0a24' })
            }
        }
    },
    {
        type: 'input',
        label: '按钮插槽',
        name: 'button',
        itemProps: {
            slots: {
                'button': () => h(Button, { type: 'primary', size: 'small' }, '尾部按钮'),
            }
        }
    },
    {
        type: 'input',
        label: '错误提示插槽',
        name: 'errorMessage',
        itemProps: {
            'errorMessage': '我错啦',
            slots: {
                'error-message': ({ message }: { message: string }) => h('span', { style: { color: 'red' } }, `错误提示插槽:${message}`)
            }
        }
    },
    {
        type: 'input',
        label: '额外内容插槽',
        name: 'extra',
        itemProps: {
            slots: {
                extra: () => h('span', { style: { color: 'green' } }, `额外内容`)
            }
        }
    },
    {
        type: 'input-slot',
        label: '自定义插槽',
        name: 'customSlot',
        itemProps: {
            slots: {
                input: () => h('div', {}, '自定义插槽'),
            }
        }
    },
])
</script>
<style lang="scss" scoped></style>
自定义插槽函数

只读表单

<template>
    <x-form :model="formValue" :items="formOptions" readonly>
    </x-form>
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import type { XFormItemOption } from 'vant4-kit';
const formValue = ref({
    name: '苏苏',
    tel: '123456789',
    idCard: '320830200012120124',
    textarea: '测试数据',
    password: '15212344567',
    checkbox: ['2'],
    slider: 20,
    rate: 3,
    switch: '1',
    picker1Text: '温州',
    picker1: 'Wenzhou'

})
const formOptions = ref<XFormItemOption>([
    {
        label: '普通输入',
        type: 'input',
        name: 'name',
    },
    {
        label: '身份证号',
        type: 'input',
        name: 'idCard',
        itemProps: {
            formatter: (val) => {
                console.log('val', val);
                return val.replace(/(\d{3})\d*(\d{4})/, '$1' + '*'.repeat(val.length - 7) + '$2');
            }
        }
    },
    {
        label: '手机号',
        type: 'input',
        name: 'tel',
        itemProps: {
            type: 'tel',
            formatter: (val) => {
                const phoneNumber = val.toString().replace(/\D/g, '');
                return phoneNumber.replace(/(\d{3})\d*(\d{4})/, '$1' + '*'.repeat(phoneNumber.length - 7) + '$2');
            }
        }
    },
    {
        label: '密码输入',
        type: 'input',
        name: 'password',
        itemProps: {
            type: 'password',
        }
    },
    {
        label: '文本域',
        type: 'input',
        name: 'textarea',
        itemProps: {
            type: 'textarea',
            row: 2,
            autosize: true,
            'show-word-limit': true,
            maxlength: 50,
        }
    },
    {
        label: '步进器',
        type: 'stepper',
        name: 'age',

    },
    {
        label: '单选',
        type: 'radio',
        name: 'sex',
        options: [
            { text: '男', value: '1' },
            { text: '女', value: '0' },

        ]
    },
    {
        label: '多选',
        type: 'checkbox',
        name: 'checkbox',
        options: [
            { text: '男', value: '1', attrs: { disabled: true } },
            { text: '女', value: '0' },
            { text: '未知', value: '2' },
        ],
        attrs: {
            shape: 'square',
        }
    },
    {
        label: '滑动',
        type: 'slider',
        name: 'slider',
    },
    {
        label: '开关',
        type: 'switch',
        name: 'switch',
        attrs: {
            activeValue: '1',
            inactiveValue: '0'
        }
    },
    {
        type: 'rate',
        label: 'rate 评分',
        name: 'rate',
        attrs: {
            count: 6
        },
    },

    {
        label: '选择器',
        type: 'picker',
        name: 'picker1',
        options: [
            { text: '杭州', value: 'Hangzhou' },
            { text: '宁波', value: 'Ningbo' },
            { text: '温州', value: 'Wenzhou' },
            { text: '绍兴', value: 'Shaoxing' },
            { text: '湖州', value: 'Huzhou' },
        ],
    },
    {
        type: 'date-picker',
        label: '日期',
        name: 'datePicker',
        attrs: {
            // 'columns-type': ['year']
        }
    },
    {
        type: 'date-picker',
        label: '日期(年份)',
        name: 'datePicker2',
        attrs: {
            'columns-type': ['year']
        },
    },
    {
        type: 'time-picker',
        label: '时间选择',
        name: 'timePicker',
        attrs: {
        }
    },
    {
        type: 'date-range-picker',
        label: '日期范围',
        name: 'dateRangePicker',
        attrs: {
        }
    },
    {
        type: 'time-range-picker',
        label: '时间范围',
        name: 'timeRangePicker',
        attrs: {
        }
    },
    {
        type: 'datetime-range-picker',
        label: '日期时间范围',
        name: 'datetimeRangePicker',
        attrs: {
            groupProps: [
                { 'columns-type': ['hour', 'minute',] },
                { 'columns-type': ['hour', 'minute', 'second'] }
            ]
        }
    },
])
</script>
<style lang="scss" scoped></style>
只读表单

Api

Props 参数

XForm 组件支持 VantForm 组件的所有属性,具体属性请参考 Vant Form,以下是 XForm 组件特有的属性

参数说明类型默认值
model搜集表单组件产生的值object{}
items表单组件渲染配置,参见:items的表单项配置对象XFormItemRow[][]
rules设置表单组件的检验规则object{}
inset是否展示为圆角卡片风格booleantrue

items的表单项配置对象

参数说明类型是否必填
type需要渲染的组件类型,参见:支持的组件类型CompType✅️
prop表单项标识keystring✅️
label表单项名称string❌️
required是否显示表单必填星号boolean❌️
rules表单校验规则Record<string,FieldRule[]>❌️
itemProps表单项目配置props(即:Field参数)object❌️
attrstype 对应原始组件的属性及方法,针对个别组件的辅助增强特性参见下文的attrs 辅助特性object❌️
options选择类组件的选择项PickerOption[]❌️
vif是否显示当前表单项,默认trueboolean | ((values: Record<string,any>) => boolean);❌️
hiddenLabel是否隐藏label内容区域boolean❌️

attrs 辅助特性

✨ 辅助特性 1️⃣ (cascader )

type: 'cascader' 时,可以配置 attrs下的 useVantAreaDatatrue 来使用Vant提供的全国区域选择数据,或者自定义 options

ts
...,
{
    type:'cascader',
    label:'地区选择',
    name:'area',
    attrs:{
        useVantAreaData: true
    }
}
...

✨ 辅助特性 2️⃣(datetime-picker)

type: 'datetime-picker' 时,可以通过在 attrs 中配置 showType 来选择选择器类型是单页形式还是分组形式

showType 可选值有 singlegroup,默认为 group

ts
// showType=single 时, 
// groupProps参数配置参考: /md/components/datetime-picker/#props-参数  
{
    type:'datetime-picker',
    label:'日期时间',
    name:'datetime',
    attrs:{
        showType: 'single',
        groupProps: {}
    }
}
// or

// showType=group 时 
// groupProps[0]的参数配置参考:https://vant.pro/vant/#/zh-CN/date-picker#props
// groupProps[1]的参数配置参考:https://vant.pro/vant/#/zh-CN/time-picker#props
{
    type:'datetime-picker',
    label:'日期时间',
    name:'datetime',
    attrs:{
        showType: 'group',
        groupProps: [
            {},
            {}
        ]
    }
}

✨ 辅助特性 3️⃣(范围选择器 )

配置的组件类型为如下三种时,对应的attrs 均存在 groupProps 数组。

  • date-range-picker

groupProps[0] 参考:Vant DatePicker

groupProps[1] 参考:Vant DatePicker

  • time-range-picker

groupProps[0] 参考:Vant TimePicker

groupProps[1] 参考:Vant TimePicker

  • datetime-range-picker

groupProps[0] 参考:DateTimePicker

groupProps[1] 参考:DateTimePicker

Events 事件

submitfailed 两种事件外,其他事件在触发时才返回的参数中,第一个参数 prop为触发此事件的组件唯一标识

事件名说明回调参数
submit提交表单且验证通过后触发values: object
failed提交表单且验证不通过后触发errorInfo: { values: object, errors: object[] }
change具备change事件的组件选项改变时触发prop:string,args:any
child-changeoptions 中需具备change事件选择项在选项改变时触发,如果checkboxprop:string,args:any
blur具备blur事件的组件,输入框失去焦点时触发prop:string,event: Event
focus具备focus事件的组件,输入框获得焦点时触发prop:string,event: Event
click具备click事件的组件,点击组件时触发prop:string,event: Event
child-clickoptions 中需具备click事件的选项在点击时触发,如果radiocheckbox,点击组件时触发prop:string,args:any
confirm点击弹框完成按钮时触发prop:string,{ selectedValues, selectedOptions, selectedIndexes }
cancel点击弹框取消按钮时触发prop:string,{ selectedValues, selectedOptions, selectedIndexes }
drag-startslider 类型组件,开始拖动时触发prop:string,event: TouchEvent
drag-endslider 类型组件,结束拖动时触发prop:string,event: TouchEvent
plusstepper类型组件,点击增加按钮时触发prop:string
minusstepper类型组件,点击减少按钮时触发prop:string
overlimitstepper类型组件,点击不可用的按钮时触发prop:string
finishcascader 类型组件,全部选项选择完成后触发prop:string,{ value: Numeric, selectedOptions: CascaderOption[], tabIndex: number }
click-tabcascader 类型组件,点击标签时触发prop:string,tabIndex: number, title: string

Slots 插槽

针对片options 配置的参数 prop对应的value值为唯一属性来自定义对应部分Field组件的插槽内容

名称说明参数
[prop值]自定义type='input-slot',prop=[prop值]的Field输入框位置渲染内容 或 自定义 type='slot',prop=[prop值] 渲染内容-
[prop值].label自定义标识为prop的输入框左侧文本-
[prop值].left-icon自定义标识为prop的输入框头部图标-
[prop值].right-icon自定义标识为prop的输入框尾部图标-
[prop值].button自定义标识为prop的输入框尾部按钮-
[prop值].error-message自定义标识为prop的组件底部错误提示文案{ message: string }
[prop值].extra自定义标识为prop的输入框最右侧的额外内容-

Expose 实例方法

通过 ref 可以获取到 XForm 实例并调用实例方法。XForm支持Vant Form所有的实例化方法

支持的组件类型

组件类型对应Vant组件说明
inputField 输入框
pickerPicker 选择器
cascaderCascader 级联选择
areaArea 省市区选择
radioRadio 单选框
checkboxCheckbox 复选框
date-pickerDatePicker 日期选择
time-pickerTimePicker 时间选择
datetime-picker-新定义组合类组件
date-range-picker-新定义组合类组件
time-range-picker-新定义组合类组件
datetime-range-picker-新定义组件
switchSwitch 开关
rateRate 评分
sliderSlider 滑块
stepperStepper 步进器
text-渲染普通文本
html-渲染html片段
input-slot-自定义Field input插槽
slot-自定义form-item

XForm类型定义

类型申明
ts
type SelectComp = 'picker' | 'cascader' | 'area' | 'radio' | 'checkbox';
type InputComp = 'input';
type DateComp = 'date-picker' | 'time-picker' | 'datetime-picker' | 'date-range-picker' | 'time-range-picker' | 'datetime-range-picker';
type OtherComp = 'switch' | 'rate' | 'slider' | 'stepper' | 'text' | 'html' | 'slot' | 'input-slot';
export type CompTypes = SelectComp | InputComp | DateComp | OtherComp;

export type XFormItemRow<T extends CompTypes = CompTypes> = {
    type: T;
    label?: string;
    name: string;
    required?: boolean;
    attrs?: (T extends keyof CompAttrsPropsMap ? (CompAttrsPropsMap[T] & Indexable) : Indexable) & { slots?: { [k: string]: (...args: any) => any } };
    vif?: boolean | ((values: Indexable) => boolean);
    rules?: FieldRule[];
    itemProps?: Partial<FieldProps> & { slots?: XFormItemSlots<T> } & Indexable;
    hiddenLabel?: boolean;
    popup?: PopupProps
} & OptionsRow<T>

export type PickerOption<T> = {
    text: string;
    value: Numeric;
    children?: PickerOption<T>[];
} & T extends 'radio' | 'checkbox' ? {
    attrs: T extends 'radio' ? RadioProps : CheckboxProps;
} : Indexable;
export type OptionsRow<T> = T extends SelectComp ? {
    options: PickerOption<T>[];
} : {
    options?: PickerOption<T>[];
};