第6课 表单与双向绑定
- 理解 v-model 双向绑定的原理(语法糖)
- 熟练使用 v-model 处理文本框、复选框、单选框、下拉框四类控件
- 掌握常用修饰符
.trim、.number - 能独立完成一个带校验和反馈的登录表单
1. v-model 双向绑定原理
1.1 什么是双向绑定
- 单向绑定(
:value):数据变 → 页面更新 - 双向绑定(
v-model):数据变 → 页面更新,同时用户输入 → 数据自动更新
1.2 v-model 是语法糖
下面两行代码完全等价:
<inputv-model="message"/><input:value="message"@input="message = $event.target.value"/>v-model 自动做了两件事:
- 将数据的值绑定到控件的
value/checked属性 - 监听控件的
input/change事件,把最新值写回数据
1.3 不同控件的内部机制
| 控件 | 绑定的属性 | 监听的事件 |
|---|---|---|
| 文本框 / 文本域 | value | input |
| 复选框 / 单选框 | checked | change |
| 下拉选择框 | value | change |
不需要背诵,但遇到奇怪表现时可回查此表。
2. 四类控件的 v-model 用法
2.1 文本框 / 密码框 / 文本域(绑定字符串)
<inputv-model="form.username"type="text"placeholder="请输入账号"/><inputv-model="form.password"type="password"/><textareav-model="form.intro"placeholder="介绍一下自己"></textarea>- 输入什么,数据就是什么,实时同步。
2.2 复选框
单个复选框(绑定布尔值)
<inputtype="checkbox"v-model="form.agree"/>同意协议<!-- form.agree 为 true / false -->适用于:记住我、同意条款、开关选项。
多个复选框(绑定数组)
<inputtype="checkbox"value="编程"v-model="form.hobbies"/>编程<inputtype="checkbox"value="音乐"v-model="form.hobbies"/>音乐<inputtype="checkbox"value="运动"v-model="form.hobbies"/>运动<!-- 选中编程和音乐后:form.hobbies = ['编程', '音乐'] -->每个复选框必须有value属性,选中的 value 会存入数组,取消时自动移除。
2.3 单选框(绑定选中项的 value)
<inputtype="radio"value="男"v-model="form.gender"/>男<inputtype="radio"value="女"v-model="form.gender"/>女<!-- 选中男 → form.gender = '男' -->关键:同一组的 radio 必须绑定同一个数据,才能实现互斥。
2.4 下拉选择框
<selectv-model="form.city"><optionvalue="">请选择城市</option><optionvalue="北京">北京</option><optionvalue="上海">上海</option></select><!-- 选中上海 → form.city = '上海' -->v-model绑定的数据会匹配option的value;如果没有value,则取标签内的文本。
2.5 控件绑定速查表
| 控件 | 关键写法 | 绑定数据类型 | 典型场景 |
|---|---|---|---|
| 文本框/密码框/文本域 | v-model="data" | 字符串 | 账号、密码、简介 |
| 单个复选框 | v-model="data" | 布尔值 | 记住我、同意协议 |
| 多个复选框 | v-model="数组"每个带value | 数组 | 爱好、权限多选 |
| 单选框 | 多个控件绑同一个数据 | 字符串 | 性别、状态选择 |
| 下拉框 | v-model+ option 带value | 字符串 | 城市、角色选择 |
3. v-model 修饰符
修饰符可以在同步数据前自动处理输入值。
3.1.trim—— 去除首尾空格
<inputv-model.trim="form.username"/>用户输入" admin "→ 实际存入"admin"。只去首尾,中间空格保留。
3.2.number—— 自动转为数字
<inputv-model.number="form.age"type="number"/>输入18→ 存入数字18,而非字符串"18"。
注意:如果输入非数字(如"abc"),则不会转换,仍为字符串。
3.3.lazy—— 失焦后才同步
<inputv-model.lazy="keyword"/>默认是实时同步(input事件),加.lazy后改为失去焦点或按回车时才同步(change事件)。
适用于:不希望频繁触发计算或请求的大表单。
4. 实战:登录表单(完整案例模式)
4.1 数据组织
使用reactive一个对象集中管理所有表单字段,便于整体操作。
import{reactive,ref}from'vue'constloginForm=reactive({username:'',password:'',remember:false})4.2 逻辑部分(核心代码)
constloading=ref(false)// 提交中状态constmessage=ref('')// 提示文字constisSuccess=ref(false)// 提示类型asyncfunctionhandleLogin(){// ① 校验if(!loginForm.username||!loginForm.password){message.value='请输入账号和密码'isSuccess.value=falsereturn}// ② 模拟提交loading.value=truemessage.value=''awaitnewPromise(resolve=>setTimeout(resolve,800))// 模拟网络延迟// ③ 模拟验证结果if(loginForm.username==='admin'&&loginForm.password==='123456'){message.value=`登录成功!欢迎回来,${loginForm.username}`isSuccess.value=true}else{message.value='账号或密码错误'isSuccess.value=false}loading.value=false}4.3 模板关键部分
<form@submit.prevent="handleLogin"><!-- 账号:文本框 + .trim --><inputv-model.trim="loginForm.username"type="text"placeholder="请输入账号"/><!-- 密码:密码框 --><inputv-model="loginForm.password"type="password"placeholder="请输入密码"/><!-- 记住我:单个复选框 --><label><inputtype="checkbox"v-model="loginForm.remember"/>记住我</label><!-- 提交按钮:动态禁用+文案 --><buttontype="submit":disabled="loading">{{ loading ? '登录中…' : '登录' }}</button><!-- 结果提示:v-if 控制显示,动态 class 控制颜色 --><pv-if="message":class="isSuccess ? 'success' : 'error'">{{ message }}</p></form>4.4 表单提交标准流程(固定套路)
- 收集:用
reactive对象收集所有控件值 - 校验:提交时进行非空、格式等检查,不通过则中断
- 提交:进入 loading 状态,禁用按钮,调用接口(或模拟)
- 反馈:根据结果显示成功/失败提示
这个模式适用于所有管理系统表单页,后续学习 Element-Plus 表单时同样适用。
5. 常见问题自查表
| 现象 | 可能原因 | 解决方法 |
|---|---|---|
| 输入框能显示但输入后数据不更新 | 只用了:value未监听@input | 改用v-model或者手动补全@input更新逻辑 |
| 复选框状态不对(不是布尔值) | 多个复选框用了同一个非数组数据 | 多个复选框必须绑定数组;单个复选框绑布尔值 |
| 单选框无法互斥 | 各 radio 的v-model绑定的是不同变量 | 同一组 radio 必须绑定同一个数据 |
| 下拉框选中后数据为空 | <option>缺少value属性 | 给每个<option>加上value |
| 提交后页面刷新、数据丢失 | <form>未阻止默认提交行为 | 使用@submit.prevent |
| 明明输入了却提示“请输入” | 输入的是空格,或密码框变量名写错 | 文本框加.trim;检查变量名对应关系 |
| 点击按钮无反应 | 方法未绑定或函数名拼写不一致 | 检查@submit或@click绑定的函数名 |
| 控制台报 xxx is not defined | 模板中使用了未定义的变量/方法 | 确保<script setup>中已定义且拼写正确 |
小结
- v-model=
:value+@input(语法糖),自动实现双向绑定 - 不同控件:文本框绑字符串,单个复选框绑布尔,多选复选框绑数组,radio/select绑选中值
- 修饰符:
.trim去首尾空格,.number转数字,.lazy失焦触发 - 表单套路:
reactive对象收集 → 校验 → loading 提交 → 结果反馈