一、示例代码
html
<!-- 1. :model 语法:el-form 表单绑定 -->
<el-form :rules="inputRules" :model="searchForm" ref="searchForm" ...>
<!-- 2. prop 语法:el-form-item 表单校验绑定 -->
<el-form-item label="起始日期" prop="startDate">
<!-- 3. v-model 语法:el-date-picker 输入控件双向绑定 -->
<el-date-picker v-model.trim="searchForm.startDate" ... />
</el-form-item>
<el-form-item label="结束日期" prop="endDate">
<el-date-picker v-model.trim="searchForm.endDate" ... />
</el-form-item>
</el-form>
这三个语法,是 Vue2 + Element UI 表单开发的黄金三角,缺一不可,各自承担完全不同的核心职责,下面逐个进行讲解。
二、详解一::model(v-bind:model)表单数据的根容器
1. 语法本质
:model 是 v-bind:model 的缩写,属于 Vue2 最基础的单向 Prop 绑定,核心是「数据从父级(页面)单向传递给子组件(el-form)」,子组件只能读取,不能直接修改。
2. 在代码里的作用
代码中 :model="searchForm" 是 Element UI el-form 组件的强制必填属性,作用是:
- 把你在
data()中定义的searchForm对象,绑定为 el-form 的数据源,作为整个表单的「数据根容器」; - 让
el-form能够读取searchForm里的字段值,用于表单校验、数据回显、输入关联; - 作为你后续发送接口请求的参数载体,所有用户输入最终都会汇总到这个对象中,直接传给后端。
3. 代码的底层逻辑
data() 中定义了 searchForm: {...},el-form 通过 :model="searchForm" 拿到这个对象后,就会把内部所有 v-model 绑定的字段,都关联到这个对象上。
当你点击「查询」按钮时,最终发送给后端的请求参数,就是这个 searchForm 对象:
javascript
// 代码里的查询方法
search(title) {
// ...
let query = Object.assign(
{
pageIndex: (this.page - 1) * this.per_page,
pageSize: this.per_page
},
this.searchForm // 这里就是 :model 绑定的数据源,直接作为接口参数
)
this.$axios({
method: 'post',
url: Api.PT1721,
params: query
})
// ...
}
4. 核心特性
- 单向数据流:
el-form只会读取searchForm,不会直接修改它,数据修改完全由内部的v-model完成; - 只读性:不能用
v-model替换:model,否则会破坏 Vue 单向数据流原则,导致表单校验失效、数据错乱; - 全局关联性:
el-form内部所有el-form-item、输入控件,都依赖这个:model绑定的对象,是整个表单的「数据底座」。
5. 关键小细节
那么如果Data()里的searchForm没有定义是空的呢?
例如:
javascript
data() {
return {
searchForm: {} // 空对象
}
}
**其实这样依旧可以绑定查询条件发送给后端,**但是!!!
这根本原因是 v-model,虽然data 中只有空对象 searchForm: {},但 v-model 具有 「动态给对象添加属性并触发响应式」 的特殊能力,所以数据能收集到。
当你在页面输入内容或选择日期时,通过事件触发赋值:
javascript
// 伪代码
this.searchForm.startDate = '2026-04-06'
哪怕这个 startDate 属性在 data 里原本不存在,Vue 也会动态给 searchForm 增加这个属性,并且让它变成响应式的。所以数据确实能收集到,提交时也能发给后端。
虽然 数据收集(v-model) 能工作,但 表单校验(rules) 是绝对会失效的。
data里 :searchForm: {}(没有startDate)。- Element UI 的校验逻辑 :它会在挂载瞬间,去
searchForm里找startDate字段。 - 结果 :因为找不到,Element UI 内部会报错(通常是
Cannot read property 'trigger' of undefined),或者直接完全忽略该字段的校验规则。
searchForm: {}会出现的问题
------------- 问题1
假设你有一个编辑 / 回显的场景,需要后端返回数据填充表单:
javascript
// 后端返回的数据
const res = { endDate: "2026-04-10" }
// 直接赋值
this.searchForm = res
如果你的 data 里定义了 searchForm: { endDate: '' },没问题。
但如果你的 data 里是 searchForm: {},且你是靠 v-model 动态加字段:
- 第一次进入编辑页,
searchForm会有endDate,显示正常。 - 但是!一旦你点击重置按钮 ,执行
this.searchForm = {}清空。 - 你的表单里的
el-date-picker会瞬间变成NaN或Invalid Date,因为 Vue 无法监听对象属性的删除(这是 Vue 2 的限制),导致组件内部状态混乱。
------------- 问题2
下次查询时候还会携带之前的查询条件
比如你上次搜了 "张三",这次不输入,点查询 → 依然带着 userName=张三
只要data 里的searchForm没有你输入的字段,Vue 响应式系统监听不到这种动态属性的删除
推荐正规写法
1. data 里必须初始化所有字段
javascript
data() {
return {
searchForm: {
userName: '',
phone: '',
status: '',
startDate: '',
endDate: ''
// 所有用到的字段都写出来
}
}
}
2. 重置方法必须这样写
javascript
reset() {
// 直接重置为初始状态
this.searchForm = {
userName: '',
phone: '',
status: '',
startDate: '',
endDate: ''
}
}
三、详解二:v-model ------ 输入控件的「双向同步器」
1. 语法本质
v-model 是 Vue2 内置的双向绑定语法糖 ,底层等价于 :value="数据" + @input="数据=$event.target.value",自动实现「数据更新 → 视图刷新,视图输入 → 数据同步」,无需手动监听事件。
在 Element UI 组件中,v-model 被封装为 :value + @change,适配日期选择器、下拉框等组件的输入逻辑。
2. 代码里的作用
代码中 v-model.trim="searchForm.startDate" / v-model.trim="searchForm.endDate",是 el-date-picker 日期选择器的核心绑定属性,作用是:
- 双向同步用户输入:你在日期选择器中选择了日期,
v-model会自动把值更新到searchForm.startDate/searchForm.endDate中; - 自动回显数据:如果
searchForm里有初始值,v-model会自动把值渲染到日期选择器上,实现编辑回显; - 保证接口参数最新:你在
search()方法中做的日期校验this.searchForm.startDate - this.searchForm.endDate > 0,能拿到最新的用户选择值,完全依赖v-model的自动同步。
3. 代码的底层逻辑
el-input加.trim 修饰符,作用是自动去除输入值的首尾空格。
v-model 绑定的 searchForm.startDate,和 el-form :model="searchForm" 是同一个对象,这就实现了「输入控件 → 表单容器 → 接口参数」的完整数据链路:用户选择日期 → v-model 自动同步到 searchForm → el-form 读取 searchForm 做校验 → search() 方法把 searchForm 作为参数发送给后端
4. 核心特性
- 双向绑定:视图和数据双向自动同步,改数据 = 改页面,改页面 = 改数据;
- 输入控件专属 :所有用户输入类组件(input、select、date-picker、radio、checkbox 等),必须用
v-model绑定; - 修饰符支持 :
.trim(去空格)、.number(转数字)、.lazy(失焦同步),优化输入体验; - 接口请求核心:收集用户输入的所有数据,是保证接口参数准确的核心。
5. 业务场景总结
- **100% 的使用场景:**所有表单输入控件,是前端收集用户输入的核心方式;
- **接口请求作用:**实时同步用户输入,保证请求参数是最新、最准确的值;
- **核心价值:**告别手动监听
@input/@change事件,大幅简化表单开发。
四、详解三:prop ------ 表单校验的「规则映射器」
1. 语法本质
prop 是 Element UI el-form-item 组件的专属属性,本质是「表单校验规则的映射字段」,作用是把 el-form-item 和 :model 绑定的对象中的某个字段、rules 中的某条校验规则,三者关联起来。
2. 代码里的作用
代码中 prop="startDate" / prop="endDate",是 el-form-item 的校验绑定属性,作用是:
- 把当前
el-form-item,和:model="searchForm"中的startDate/endDate字段做绑定; - 把当前
el-form-item,和你在data()中定义的inputRules校验规则中的startDate/endDate规则做绑定; - 让
el-form执行validate()校验时,能精准找到对应的字段和规则,完成校验、错误提示。
3. 代码的底层逻辑
在 data() 中定义了校验规则:
javascript
inputRules: {
startDate: [
{ required: true, message: '起始日期不能为空', trigger: 'blur' }
],
endDate: [
{ required: true, message: '结束日期不能为空', trigger: 'blur' }
]
}
当你给 el-form-item 写 prop="startDate" 时,el-form 就会自动做三件事:
- 从
:model="searchForm"中,读取startDate字段的值; - 从
inputRules中,读取startDate对应的校验规则; - 当用户触发
blur失焦事件,或调用this.$refs.searchForm.validate()时,执行校验,不符合规则就显示错误提示。
如果不写 prop 属性,el-form 就无法找到对应的字段和规则,表单校验会完全失效,这是 Element UI 表单校验的核心要求。
4. 核心特性
- el-form-item 专属:仅用于
el-form内部的el-form-item组件,其他组件不支持; - 校验映射核心:是
el-form表单校验生效的必要条件,没有prop就没有校验; - 字段一致性要求:
prop的值,必须和:model绑定对象的字段名、rules中的规则名完全一致(比如prop="startDate",searchForm必须有startDate字段,rules必须有startDate规则); - 错误提示关联:校验不通过时,错误提示会自动显示在当前
el-form-item下方,和prop绑定的字段一一对应。
5. 业务场景总结
- **唯一使用场景:**Element UI el-form 表单的 el-form-item 组件,用于表单校验;
- **接口请求作用:**保证用户输入符合业务规则,避免无效数据发送给后端;
- **核心价值:**实现表单的自动化校验,无需手动写校验逻辑,大幅提升开发效率。
五、三者核心区别
| 对比维度 | :model(v-bind:model) |
v-model |
prop |
|---|---|---|---|
| 语法本质 | 单向 Prop 绑定(v-bind 缩写) | 双向绑定语法糖 | el-form-item 专属校验映射属性 |
| 绑定对象 | el-form 表单组件 | 输入控件(el-date-picker/el-input 等) | el-form-item 表单项组件 |
| 核心作用 | 表单数据根容器,承载所有接口参数 | 输入控件双向同步,收集用户输入 | 校验规则映射,让表单校验生效 |
| 数据流向 | 页面 → el-form(单向只读) | 输入控件 ↔ searchForm(双向自动同步) | 无数据传递,仅做规则映射 |
| 代码中的位置 | <el-form :model="searchForm"> |
<el-date-picker v-model="searchForm.startDate"> |
<el-form-item prop="startDate"> |
| 接口请求作用 | 存储最终发送的请求参数 | 同步用户输入,保证参数最新 | 校验输入合法性,过滤无效请求 |
| 是否必填 | el-form 必写,否则表单无数据源 | 输入控件必写,否则无法收集输入 | 有校验需求必写,否则校验失效 |
| 依赖关系 | 是 v-model、prop 的数据基础 | 依赖 :model 绑定的对象 | 依赖 :model 和 rules 校验规则 |
| 底层原理 | v-bind 单向传值 | :value + @input(语法糖) | 字段 - 规则 - 表单项的映射关联 |
六、三者协同工作的完整链路
我们用「日期查询表单」,完整走一遍三者的协作流程:
步骤 1:页面初始化
data()中定义searchForm、inputRules等数据;el-form通过:model="searchForm"绑定数据源,通过:rules="inputRules"绑定校验规则;el-form-item通过prop="startDate"/prop="endDate",把表单项、searchForm字段、inputRules规则三者关联;el-date-picker通过v-model="searchForm.startDate",把输入控件和searchForm字段双向绑定。
步骤 2:用户操作(选择日期)
- 用户在
el-date-picker中选择起始日期; v-model自动把选择的日期,同步到searchForm.startDate中;- 用户失焦时,
el-form根据prop="startDate"找到对应的字段和规则,执行校验; - 校验通过,无错误提示;校验不通过,显示「起始日期不能为空」的错误提示。
步骤 3:点击「查询」按钮,发送接口请求
- 执行
search()方法,先做日期大小校验this.searchForm.startDate - this.searchForm.endDate > 0; - 调用
this.$refs.searchForm.validate()触发表单校验,el-form根据prop映射的规则,校验searchForm中的字段; - 校验通过后,把
searchForm拼接到query对象中,作为接口参数发送给后端; - 后端返回数据,渲染到表格中,完成一次完整的查询流程。
步骤 4:点击「重置」按钮
- 执行
resetForm()方法,重置searchForm中的startDate/endDate字段; v-model监听到searchForm数据变化,自动清空el-date-picker的显示;el-form调用resetFields()方法,根据prop映射的字段,清空校验状态,移除错误提示。
