Vue3 表单绑定
表单是收集用户输入的主力,原生写法要监听 input 事件、再读 value 写回数据,两行联动。
Vue 的 v-model 一句搞定,它本质上是”值和事件”的组合,帮你完成这一来一回。
v-model 是什么
v-model="xxx" 等价于同时做了两件事:
<input v-model="keyword" />
<!-- 等价于 -->
<input :value="keyword" @input="keyword = $event.target.value" />
拆开看这句等价式里的两个部分:
:value="keyword":把变量的值放进输入框显示。@input:input是”用户输入时”触发的原生事件(上篇 Vue3 事件处理 讲过@绑定)。每次输入,$event.target.value是输入框当前的完整内容,把它赋回keyword,值就写回变量了。
一个管”显示”,一个管”写回”,v-model 把它们合成一行。
v-model 在不同控件上的行为由 Vue 定制好了,绝大多数表单场景直接用即可。
各控件用法
文本输入(input / textarea)
<script setup>
import { ref } from 'vue'
const keyword = ref('')
const content = ref('')
</script>
<template>
<input v-model="keyword" placeholder="搜索关键词" />
<textarea v-model="content" placeholder="多行内容"></textarea>
</template>
注意:<textarea> 不能用 {{ }} 插值,只能用 v-model。
<textarea>{{ content }}</textarea> 在 Vue 里不生效(官方不支持)。
一是历史兼容问题,二是 v-model 要同时处理”值显示”和”输入写回”,插值只负责显示一半,容易不同步,用 v-model 就对了。
单选(radio)
<script setup>
import { ref } from 'vue'
const gender = ref('男')
</script>
<template>
<input type="radio" value="男" v-model="gender" /> 男
<input type="radio" value="女" v-model="gender" /> 女
</template>
勾选(checkbox)
勾选有两种常见形态:
<!-- 单个:绑定布尔值,勾选 = true -->
<input type="checkbox" v-model="isAgree" /> 我已阅读协议
<!-- 多个:绑定数组,勾选的值自动进数组 -->
<input type="checkbox" value="篮球" v-model="hobbies" /> 篮球
<input type="checkbox" value="阅读" v-model="hobbies" /> 阅读
所以,checkbox 的 v-model到底是布尔还是数组?这里看绑定目标:
- 绑定单个变量 → 布尔(勾选 true/false)
- 绑定数组 → 把被勾选的
value收集进去。
声明错了类型就会看到”勾选没反应”,对号入座即可。
下拉(select)
<script setup>
import { ref } from 'vue'
const city = ref('北京')
const cities = ['北京', '上海', '广州']
</script>
<template>
<select v-model="city">
<option v-for="c in cities" :key="c" :value="c">{{ c }}</option>
</select>
</template>
v-model 修饰符
上篇 Vue3 事件处理 讲过”事件修饰符”(.stop、.prevent…),那是挂在事件上的;这里 v-model 后面也能加点修饰符,管的不是事件,而是”值怎么存进变量”,两者名字都叫修饰符,但作用对象完全不同。
| 修饰符 | 作用 | 示例 |
|---|---|---|
.lazy |
改成失焦时更新(原生 change 事件,区别于立即触发的 input) |
v-model.lazy |
.number |
自动把输入转成数字 | v-model.number |
.trim |
自动去掉首尾空格 | v-model.trim |
<!-- 不 trim 的话," 你好 " 会带空格存进变量 -->
<input v-model.trim="keyword" />
<!-- 表单经常用 number + trim 组合 -->
<input v-model.number="price" />
.number 有个细节:输入开头是能转数字的内容才转("12abc" 会保留为字符串),别指望它对所有输入都”安全转型”。
速查卡片
| 控件 | 绑定目标 | 说明 |
|---|---|---|
| input/text/textarea | ref('') |
文本直接绑定 |
| radio | ref('') |
与 value 匹配高亮 |
| checkbox 单个 | ref(false) |
布尔 |
| checkbox 多个 | ref([]) |
收集选中 value 到数组 |
| select | ref('') |
与 option 的 value 匹配 |
| 常用修饰 | .lazy .number .trim |
失焦/数字/去空格 |