Element Plus 2.x 配合 Vue 3.2+ 和 TypeScript 4.5+ 时,表单类组件的核心是数据绑定、规则验证和值格式控制。下面按 Form、DatePicker、DateTimePicker、TimePicker、TimeSelect、ColorPicker 的使用路径重组原文代码与 API,并给出容易出错的排查点。
一、Form:用 ref 获取实例,用 rules 管理验证
通过 ref<FormInstance>() 获取表单实例,reactive 创建 model,FormRules 定义规则。required、min、max、type、trigger 分别控制必填、长度、邮箱格式和触发时机。提交时调用 formRef.value.validate 回调,valid 为 true 才提交;重置调用 resetFields。- <script setup lang='ts'>
- import { ref, reactive } from 'vue'
- import type { FormInstance, FormRules } from 'element-plus'
- const formRef = ref<FormInstance>()
- const form = reactive({ username: '', password: '', email: '' })
- const rules = reactive<FormRules>({
- username: [
- { required: true, message: '请输入用户名', trigger: 'blur' },
- { min: 3, max: 20, message: '长度在 3 到 20 个字符', trigger: 'blur' }
- ],
- password: [
- { required: true, message: '请输入密码', trigger: 'blur' },
- { min: 6, message: '密码至少 6 位', trigger: 'blur' }
- ],
- email: [
- { required: true, message: '请输入邮箱', trigger: 'blur' },
- { type: 'email', message: '请输入正确的邮箱格式', trigger: 'blur' }
- ]
- })
- const handleSubmit = async () => {
- if (!formRef.value) return
- await formRef.value.validate((valid) => {
- if (valid) console.log('提交成功', form)
- else console.log('验证失败')
- })
- }
- const handleReset = () => { formRef.value?.resetFields() }
- </script>
- <template>
- <el-form ref='formRef' :model='form' :rules='rules' label-width='80px'>
- <el-form-item label='用户名' prop='username'>
- <el-input v-model='form.username' placeholder='请输入用户名' />
- </el-form-item>
- </el-form>
- </template>
复制代码
自定义验证器用于确认密码等跨字段校验:validator 接收 rule、value、callback,比较 value 与 form.password,不一致时 callback(new Error('两次输入密码不一致')),一致时 callback()。注意必须调用 callback 返回结果。- const validateConfirmPassword = (rule: any, value: any, callback: any) => {
- if (value !== form.password) callback(new Error('两次输入密码不一致'))
- else callback()
- }
- const rules = reactive<FormRules>({
- confirmPassword: [
- { required: true, message: '请再次输入密码', trigger: 'blur' },
- { validator: validateConfirmPassword, trigger: 'blur' }
- ]
- })
复制代码
动态表单用 domains 数组保存行数据,addDomain 通过 Date.now() 生成 key 并 push,removeDomain 用 splice 删除。原文提醒:动态表单的 prop 需要使用数组索引,例如 prop='domains.0.value'。行内查询表单直接设置 :inline='true',配合 el-form-item 和 el-select 使用。- const addDomain = () => { form.domains.push({ key: Date.now(), value: '' }) }
- const removeDomain = (index: number) => { form.domains.splice(index, 1) }
复制代码
Form 排查点:prop 必须与 model 字段名一致;自定义验证器必须调用 callback;resetFields 会重置为初始值并清除验证状态;el-form 还提供 validateField、clearValidate、scrollToField 等方法。
二、DatePicker:范围、禁用日期与快捷选项
DatePicker 的 type 可取 year、month、date、dates、week、daterange、monthrange 等。日期范围选择时 v-model 为数组,format 控制显示格式,value-format 控制绑定值格式,原文推荐使用 YYYY-MM-DD。- <el-date-picker v-model='dateRange' type='daterange' start-placeholder='开始日期' end-placeholder='结束日期' format='YYYY-MM-DD' value-format='YYYY-MM-DD' />
复制代码
限制可选日期通过 disabled-date 函数完成,返回 true 表示禁用。下面示例禁用今天之前的日期,以及只允许选择工作日。- const disabledDate = (time: Date) => time.getTime() < Date.now() - 8.64e7
- const disabledWeekends = (time: Date) => {
- const day = time.getDay()
- return day === 0 || day === 6
- }
复制代码
快捷选项使用 shortcuts 数组,value 可以是返回 Date 数组的函数。原文给出的最近一周、最近一个月、最近三个月分别按 3600 * 1000 * 24 * 7、30、90 计算。- const shortcuts = [
- { text: '最近一周', value: () => { const end = new Date(); const start = new Date(); start.setTime(start.getTime() - 3600 * 1000 * 24 * 7); return [start, end] } },
- { text: '最近一个月', value: () => { const end = new Date(); const start = new Date(); start.setTime(start.getTime() - 3600 * 1000 * 24 * 30); return [start, end] } },
- { text: '最近三个月', value: () => { const end = new Date(); const start = new Date(); start.setTime(start.getTime() - 3600 * 1000 * 24 * 90); return [start, end] } }
- ]
复制代码
三、DateTimePicker:精确到时分秒
需要选择日期时间时使用 type='datetime',日期时间范围使用 type='datetimerange'。default-time 可设置选中日期后的默认时间,例如 new Date(2024, 0, 1, 9, 0, 0) 对应 2024-01-01 09:00:00。时间格式中 HH 为 24 小时制,hh 为 12 小时制。- <el-date-picker v-model='dateTime' type='datetime' format='YYYY-MM-DD HH:mm:ss' value-format='YYYY-MM-DD HH:mm:ss' :default-time='defaultTime' />
复制代码
四、TimePicker:固定间隔与时间范围
TimePicker 通过 format、value-format 控制时间格式,is-range 开启时间范围选择。disabled-hours、disabled-minutes、disabled-seconds 接收函数,返回需要禁用的小时、分钟、秒数组。- <el-time-picker v-model='timeRange' is-range start-placeholder='开始时间' end-placeholder='结束时间' />
- const disabledHours = () => [...Array(9).keys(), ...Array(6).keys().map(i => i + 18)]
- const disabledMinutes = (hour: number) => (hour === 9 || hour === 17) ? [0, 1, 2, 3, 4, 5] : []
复制代码
五、TimeSelect:固定时间列表
TimeSelect 适合预约、排班等固定时间列表场景。start、end 控制起止时间,step 控制间隔,时间格式为 HH:mm,例如 step='00:30' 表示 30 分钟一档。- <el-time-select v-model='time' start='09:00' end='18:00' step='00:30' placeholder='选择时间' />
复制代码
六、ColorPicker:透明度与预设颜色
ColorPicker 支持 hex、rgb、hsv 等颜色格式。show-alpha 开启透明度选择,predefine 传入预设颜色数组。- <el-color-picker v-model='color' show-alpha :predefine='predefineColors' />
- const predefineColors = ['#ff4500', '#ff8c00', '#ffd700', '#90ee90', '#00ced1', '#1e90ff', '#c71585']
复制代码
七、实践中的排查顺序
先检查 el-form 的 model、rules 是否绑定正确,再检查 el-form-item 的 prop 是否与字段路径一致;跨字段验证要确认 callback 被调用;日期范围要确认 v-model 是数组;需要字符串提交时统一设置 value-format;禁用日期函数返回布尔值;时间禁用函数返回数组;TimeSelect 的 step 不要写成非法时间格式;ColorPicker 预设颜色使用数组传入。按这个顺序排查,大部分表单组件的绑定与格式问题都能快速定位。 |