一、v-model:表单绑定的语法糖
在Vue中处理表单输入时,我们需要将输入值与组件状态同步。手动实现需绑定value属性并监听input/change事件,而v-model是简化这一过程的语法糖------它自动完成"值绑定+事件监听",让代码更简洁。
v-model的核心逻辑是:
vue
<!-- v-model="data" 等价于 -->
<input :value="data" @input="data = $event.target.value" />
它会根据输入类型自动适配DOM属性和事件:
- 文本/多行文本:
value属性 +input事件 - 复选框/单选框:
checked属性 +change事件 - 选择器:
value属性 +change事件
往期文章归档
-
只给表子集建索引?用函数结果建索引?PostgreSQL这俩操作凭啥能省空间又加速? - cmdragon's Blog
-
想抓PostgreSQL里的慢SQL?pg_stat_statements基础黑匣子和pg_stat_monitor时间窗,谁能帮你更准揪出性能小偷? - cmdragon's Blog
-
PostgreSQL 查询慢?是不是忘了优化 GROUP BY、ORDER BY 和窗口函数? - cmdragon's Blog
-
PostgreSQL选Join策略有啥小九九?Nested Loop/Merge/Hash谁是它的菜? - cmdragon's Blog
-
PostgreSQL索引选B-Tree还是GiST?"瑞士军刀"和"多面手"的差别你居然还不知道? - cmdragon's Blog
-
PostgreSQL处理SQL居然像做蛋糕?解析到执行的4步里藏着多少查询优化的小心机? - cmdragon's Blog
-
PostgreSQL备份不是复制文件?物理vs逻辑咋选?误删还能精准恢复到1分钟前? - cmdragon's Blog
-
PostgreSQL里的PL/pgSQL到底是啥?能让SQL从"说目标"变"讲步骤"? - cmdragon's Blog
-
PostgreSQL UPDATE语句怎么玩?从改邮箱到批量更新的避坑技巧你都会吗? - cmdragon's Blog
-
PostgreSQL 17安装总翻车?Windows/macOS/Linux避坑指南帮你搞定? - cmdragon's Blog
-
能当关系型数据库还能玩对象特性,能拆复杂查询还能自动管库存,PostgreSQL凭什么这么香? - cmdragon's Blog
-
如何在FastAPI中巧妙隔离依赖项,让单元测试不再头疼? - cmdragon's Blog
免费好用的热门在线工具
1.1 文本输入:单行与多行
单行文本
最基础的输入类型,v-model直接绑定响应式变量:
vue
<template>
<!-- 实时显示输入内容 -->
<p>输入的内容:{{ message }}</p>
<!-- v-model同步输入与message -->
<input v-model="message" placeholder="请输入" />
</template>
<script setup>
import { ref } from 'vue'
// 初始值在JS侧声明(而非DOM的value属性)
const message = ref('')
</script>
多行文本
<textarea>需用v-model绑定(不能用插值{{ }}):
vue
<template>
<!-- 保留换行符(white-space: pre-line) -->
<p style="white-space: pre-line;">多行内容:{{ message }}</p>
<textarea v-model="message" placeholder="请输入多行内容"></textarea>
</template>
<script setup>
import { ref } from 'vue'
const message = ref('')
</script>
1.2 复选框:布尔值与数组
单个复选框
绑定布尔值,适用于"同意协议"等场景:
vue
<template>
<input type="checkbox" id="agree" v-model="isAgreed" />
<label for="agree">{{ isAgreed ? '已同意' : '未同意' }}</label>
</template>
<script setup>
import { ref } from 'vue'
const isAgreed = ref(false) // 初始未同意
</script>
多个复选框
绑定数组,选中的项会自动加入数组:
vue
<template>
<div>选中的名字:{{ checkedNames }}</div>
<input type="checkbox" id="jack" value="Jack" v-model="checkedNames" />
<label for="jack">Jack</label>
<input type="checkbox" id="john" value="John" v-model="checkedNames" />
<label for="john">John</label>
</template>
<script setup>
import { ref } from 'vue'
const checkedNames = ref([]) // 初始为空数组
</script>
1.3 单选框:互斥选择的绑定
单选框组绑定到同一个变量,选中的value会赋值给变量:
vue
<template>
<div>选中的选项:{{ picked }}</div>
<input type="radio" id="one" value="One" v-model="picked" />
<label for="one">One</label>
<input type="radio" id="two" value="Two" v-model="picked" />
<label for="two">Two</label>
</template>
<script setup>
import { ref } from 'vue'
const picked = ref('One') // 初始选中One
</script>
1.4 选择器:单选与多选
单选选择器
v-model绑定字符串,需添加disabled的空值选项(解决iOS兼容问题):
vue
<template>
<div>选中的选项:{{ selected }}</div>
<select v-model="selected">
<!-- 解决iOS无法选第一个选项的问题 -->
<option disabled value="">请选择</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
</template>
<script setup>
import { ref } from 'vue'
const selected = ref('') // 初始为空
</script>
多选选择器
添加multiple属性,v-model绑定数组:
vue
<template>
<div>选中的选项:{{ selected }}</div>
<select v-model="selected" multiple>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
</template>
<script setup>
import { ref } from 'vue'
const selected = ref([]) // 初始为空数组
</script>
动态选项
用v-for渲染动态选项(常见于从接口获取数据的场景):
vue
<template>
<select v-model="selected">
<option v-for="option in options" :value="option.value">
{{ option.text }}
</option>
</select>
</template>
<script setup>
import { ref } from 'vue'
const selected = ref('A')
// 动态选项列表(可从接口获取)
const options = ref([
{ text: '选项一', value: 'A' },
{ text: '选项二', value: 'B' },
{ text: '选项三', value: 'C' }
])
</script>
二、值绑定:动态值的处理
默认情况下,v-model的value是静态字符串/布尔值 ,但有时需要绑定动态值 (如组件属性、对象),这时需用v-bind(或简写:)。
2.1 复选框的动态true/false值
用true-value和false-value指定选中/未选中时的值(非布尔值):
vue
<template>
<input
type="checkbox"
v-model="toggle"
true-value="yes"
false-value="no"
/>
<p>当前值:{{ toggle }}</p> <!-- 选中为"yes",未选中为"no" -->
</template>
<script setup>
import { ref } from 'vue'
const toggle = ref('no') // 初始未选中
</script>
2.2 单选框的动态值
绑定value到组件的动态属性(如接口返回的值):
vue
<template>
<input type="radio" v-model="pick" :value="option1" />
<label>选项一</label>
<input type="radio" v-model="pick" :value="option2" />
<label>选项二</label>
<p>选中的值:{{ pick }}</p>
</template>
<script setup>
import { ref } from 'vue'
// 动态值(可从接口获取)
const option1 = ref('动态值1')
const option2 = ref('动态值2')
const pick = ref(option1.value) // 初始选中选项一
</script>
2.3 选择器的对象值
option的value可以是对象(传递更多信息):
vue
<template>
<select v-model="selected">
<option :value="{ id: 1, name: '张三' }">张三</option>
<option :value="{ id: 2, name: '李四' }">李四</option>
</select>
<p>选中的用户:{{ selected.name }}</p> <!-- 显示用户名 -->
</template>
<script setup>
import { ref } from 'vue'
const selected = ref({ id: 1, name: '张三' }) // 初始选中张三
</script>
三、修饰符:定制v-model的行为
v-model提供三个修饰符,调整同步时机或值的处理:
3.1 .lazy:延迟同步到change事件
默认v-model在input事件(每输入一个字符)同步,lazy改为在change事件(输入完成、失去焦点或回车)同步:
vue
<template>
<input v-model.lazy="msg" placeholder="输入完成后同步" />
<p>当前值:{{ msg }}</p> <!-- 失去焦点后才更新 -->
</template>
<script setup>
import { ref } from 'vue'
const msg = ref('')
</script>
3.2 .number:自动转换为数字
自动将输入值转为Number类型(适用于数字输入):
vue
<template>
<input v-model.number="age" type="number" placeholder="请输入年龄" />
<p>年龄类型:{{ typeof age }}</p> <!-- 输入数字时为"number" -->
</template>
<script setup>
import { ref } from 'vue'
const age = ref(0) // 初始值为数字
</script>
3.3 .trim:自动去除首尾空格
自动去除输入值的首尾空格:
vue
<template>
<input v-model.trim="msg" placeholder="输入带空格的内容" />
<p>处理后的值:"{{ msg }}"</p> <!-- 首尾空格被去除 -->
</template>
<script setup>
import { ref } from 'vue'
const msg = ref('')
</script>
四、课后Quiz:巩固你的理解
问题1
v-model在文本输入框 和复选框 上分别对应哪些DOM属性和事件?
答案:
- 文本输入框:
value属性 +input事件; - 复选框:
checked属性 +change事件。
问题2
如何让v-model绑定的复选框值为"yes"或"no",而不是布尔值?
答案 :
使用true-value和false-value属性:
vue
<input type="checkbox" v-model="toggle" true-value="yes" false-value="no" />
问题3
.lazy修饰符的作用是什么?请写出使用.lazy的v-model示例。
答案 :
作用:将同步时机从input事件改为change事件(输入完成后同步)。
示例:
vue
<input v-model.lazy="msg" />
问题4
为什么<select>元素需要添加一个disabled的空值选项?
答案 :
若初始值不匹配任何选项,iOS会无法选中第一个选项(iOS不触发change事件)。添加空值选项可解决:
vue
<select v-model="selected">
<option disabled value="">请选择</option>
<option>A</option>
</select>
五、常见报错与解决
5.1 选择器无法选中第一个选项(iOS)
现象 :iOS设备上,<select>的第一个选项无法选中。
原因 :初始值不匹配任何选项,iOS不触发change事件。
解决 :添加disabled的空值选项(见1.4节单选选择器示例)。
5.2 IME输入时v-model不更新
现象 :输入中文、日文等需IME的语言时,v-model在组合过程中不更新。
原因 :v-model默认忽略IME组合时的输入。
解决 :手动绑定input事件和value:
vue
<template>
<input :value="msg" @input="msg = $event.target.value" />
</template>
<script setup>
import { ref } from 'vue'
const msg = ref('')
</script>
5.3 输入数字但得到字符串
现象 :输入数字后,变量类型是string而非number。
原因 :v-model默认保留原始输入类型(字符串)。
解决 :添加number修饰符:
vue
<input v-model.number="age" type="number" />
参考链接:
vuejs.org/guide/essen...