Skip to content
On this page

v-model 是 Vue 最常用的指令之一,实现表单控件和数据之间的双向绑定

什么是双向绑定?

普通的 :value 只能做到"数据 → 页面"。v-model 能做到:

数据 ↔ 页面:改数据,页面变;用户输入,数据也变。
vue
<template>
  <input v-model="message">
  <p>你输入的是:{{ message }}</p>
</template>
<script>
export default {
  data() {
    return { message: '' }
  }
}
</script>

你在输入框里打字 → message 自动更新 → 自动刷新。两个方向都是自动的。 💡 Tip:v-model 的本质v-model="message" 等价于同时做了两件事:

  1. :value="message" — 把数据绑到输入框
  2. @input="message = $event.target.value" — 监听输入并更新数据 所以它叫"双向绑定",一行顶两行。

不同表单控件的用法

文本框

vue
<input v-model="text">

文本域

vue
<textarea v-model="content"></textarea>

📝 Note:注意<textarea> 不要写 插值,用 v-model

单选复选框

vue
<input type="checkbox" v-model="checked">
<span>{{ checked ? '已选' : '未选' }}</span>

checked 的值是 truefalse

多选复选框(绑定到数组)

vue
<template>
  <div>
    <input type="checkbox" v-model="hobbies" value="读书"> 读书
    <input type="checkbox" v-model="hobbies" value="运动"> 运动
    <input type="checkbox" v-model="hobbies" value="音乐"> 音乐
    <p>你选了:{{ hobbies }}</p>
  </div>
</template>
<script>
export default {
  data() {
    return {
      hobbies: []          // 必须是数组
    }
  }
}
</script>

单选框

vue
<input type="radio" v-model="gender" value="男"> 男
<input type="radio" v-model="gender" value="女"> 女

下拉列表

vue
<select v-model="city">
  <option disabled value="">请选择城市</option>
  <option value="beijing">北京</option>
  <option value="shanghai">上海</option>
</select>

修饰符

v-model 提供了三个方便的修饰符: | 修饰符 | 作用 | 什么时候用 | | .lazy | 失去焦点时才更新数据(而不是每次输入都更新) | 输入大段文字时减少计算 | | .number | 自动把输入转成数字 | 输入年龄、价格 | | .trim | 自动去掉首尾空格 | 输入用户名、邮箱 |

vue
<input v-model.lazy="message">     <!-- 按回车或失焦才更新 -->
<input v-model.number="age">       <!-- 输入 "25" → age 是数字 25 -->
<input v-model.trim="username">    <!-- " 小明 " → "小明" -->

实际例子:登录表单

vue
<template>
  <form @submit.prevent="handleLogin">
    <div>
      <label>用户名:</label>
      <input v-model.trim="username" placeholder="请输入用户名">
    </div>
    <div>
      <label>密码:</label>
      <input v-model="password" type="password" placeholder="请输入密码">
    </div>
    <div>
      <label>
        <input type="checkbox" v-model="remember"> 记住我
      </label>
    </div>
    <button type="submit">登录</button>
  </form>
</template>
<script>
export default {
  data() {
    return {
      username: '',
      password: '',
      remember: false
    }
  },
  methods: {
    handleLogin() {
      console.log(`登录:${this.username}, 记住:${this.remember}`)
      // 这里发登录请求
    }
  }
}
</script>

新手常见问题

Q:input 事件和 v-model 冲突吗? A:不会。你仍然可以单独用 @input 做额外的处理,v-model 会继续正常运行。 Q:为什么我的 checkbox 绑定到数组,数据没更新? A:检查你的数组是用 ref 还是 reactive。组合式 API 中如果用 ref([]),用的时候要 .valueQ:v-model 能绑定 computed 吗? A:能,但需要给 computed 提供 setter。如果只是只读 computed,v-model 会报错。 下一步: 💡 Tip:Composition API 写法(Vue 3)

vue
<script setup>
import { ref } from 'vue'
const message = ref('')
const checked = ref(false)
</script>

模板中 v-model 写法完全不变。 详见: