Vue3中v-model双向绑定的避坑指南(2026最新)

 更新时间:2026年04月03日 08:39:53   作者:前端Hardy  
这篇文章主要为大家详细介绍了Vue3中v-model双向绑定的正确用法和避坑指南,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下

你的表单数据绑定了却不动?自定义组件 v-model 写了就是不生效?

而用 Vue3 正确的 v-model 写法,一行代码搞定双向绑定,支持多字段同步、自定义事件、TS 完美兼容——再也不用手动写 $emit('input').sync 修饰符!

如果你受够了:

  • 输入框改了值,页面没反应
  • 自定义组件传值像“猜谜游戏”
  • Vue2 转 Vue3 后 v-model 突然失效
  • 团队里有人写 :value + @input,有人写 v-model,代码风格混乱

那么,这篇 2026 年最新实操指南,就是为你写的——不用翻文档,所有代码模板直接复制粘贴,今天就能写出零 bug 的双向绑定

一、先搞懂:Vue3 的 v-model,到底“新”在哪?

很多从 Vue2 过来的开发者,还在用老思维写 v-model,结果频频翻车。

Vue3 对 v-model 做了三大升级

特性Vue2Vue3
绑定属性固定为 value可自定义(如 title、count)
触发事件input统一为 update:xxx
多绑定支持不支持一个组件可绑多个 v-model
语法糖需配合 .sync原生支持,无需额外修饰符

一句话总结:Vue3 的 v-model = 更灵活 + 更统一 + 更少代码。

二、核心干货:v-model 3 大场景实战(附可运行模板)

场景1:基础表单绑定(覆盖 80% 日常开发)

适用于 <input><textarea><select>、复选框等。

【实操代码】(直接复制)

<template>
  <div class="form-demo">
    <!-- 文本输入 -->
    <input v-model="username" placeholder="账号" />
    <!-- 密码 -->
    <input v-model="password" type="password" placeholder="密码" />
    <!-- 多行文本 -->
    <textarea v-model="bio" placeholder="个人简介"></textarea>
    <!-- 复选框(布尔值) -->
    <label>
      <input type="checkbox" v-model="agree" />
      同意用户协议
    </label>
    <!-- 实时预览 -->
    <div class="preview">
      账号:{{ username }}
      密码:{{ password }}
      简介:{{ bio }}
      已同意:{{ agree ? '✅' : '❌' }}
    </div>
  </div>
</template>
<script setup>
import { ref } from 'vue'
const username = ref('')
const password = ref('')
const bio = ref('')
const agree = ref(false)
</script>

避坑提醒v-model自动忽略元素上的 valuechecked 属性,不要混用

场景2:自定义组件 v-model(组件通信必备)

让自定义组件像原生表单一样使用 v-model

1. 创建组件:MyInput.vue

<template>
  <div class="my-input">
    <span>自定义:</span>
    <input
      :value="modelValue"
      @input="$emit('update:modelValue', $event.target.value)"
      placeholder="请输入..."
    />
  </div>
</template>
<script setup>
// 必须叫 modelValue!
const props = defineProps(['modelValue'])
// 必须 emit update:modelValue!
const emit = defineEmits(['update:modelValue'])
</script>

2. 父组件使用

<template>
  <MyInput v-model="customText" />
  <p>输入内容:{{ customText }}</p>
</template>

<script setup>
import { ref } from 'vue'
import MyInput from './MyInput.vue'

const customText = ref('')
</script>

效果:父组件 v-model="customText" → 子组件 modelValue 接收 → 输入时触发 update:modelValue → 父组件自动更新!

场景3:多 v-model 绑定(复杂表单神器)

一个组件同时绑定多个双向数据,比如姓名 + 年龄 + 邮箱。

父组件

<template>
  <UserForm 
    v-model:name="user.name"
    v-model:age="user.age"
    v-model:email="user.email"
  />
  <pre>{{ user }}</pre>
</template>

<script setup>
import { reactive } from 'vue'
import UserForm from './UserForm.vue'

const user = reactive({
  name: '',
  age: 0,
  email: ''
})
</script>

子组件:UserForm.vue

<template>
  <div>
    <input v-model="nameProxy" placeholder="姓名" />
    <input v-model.number="ageProxy" type="number" placeholder="年龄" />
    <input v-model="emailProxy" type="email" placeholder="邮箱" />
  </div>
</template>

<script setup>
const props = defineProps(['name', 'age', 'email'])
const emit = defineEmits(['update:name', 'update:age', 'update:email'])

// 使用计算属性代理,让 v-model 在子组件内也能用
import { computed } from 'vue'
const nameProxy = computed({
  get: () => props.name,
  set: (val) => emit('update:name', val)
})
const ageProxy = computed({
  get: () => props.age,
  set: (val) => emit('update:age', val)
})
const emailProxy = computed({
  get: () => props.email,
  set: (val) => emit('update:email', val)
})
</script>

优势:父组件只需写 v-model:xxx,逻辑清晰,维护成本极低!

三、实战避坑:90% 的人都会踩的 3 个致命错误

坑1:绑定非响应式数据

// 错误 
let text = '' // 普通变量
// v-model="text" → 修改无效!
// 正确 
const text = ref('') // 响应式

坑2:自定义组件命名不规范

// 错误(Vue2 写法)
defineProps(['value'])
defineEmits(['input'])
// 正确(Vue3 标准)
defineProps(['modelValue'])
defineEmits(['update:modelValue'])

坑3:v-model和:value混用

<!-- 错误  -->
<input v-model="msg" :value="defaultValue" />
<!-- 正确  -->
<input v-model="msg" />
<!-- 或初始化时:const msg = ref(defaultValue) -->

四、进阶技巧:用 TS 让 v-model 更安全

// MyInput.vue (TypeScript 版)
<script setup lang="ts">
interface Props {
  modelValue: string
}
const props = defineProps<Props>()
const emit = defineEmits<{
  (e: 'update:modelValue', value: string): void
}>()
</script>

类型检查 + 智能提示,杜绝拼写错误!

五、谁在用 Vue3 的 v-model?

  • 字节跳动:所有内部表单系统强制使用多 v-model 模式
  • 腾讯文档:协作编辑组件通过 v-model:content 实时同步
  • Nuxt 3 官方模板:表单示例全部采用 Composition API + v-model
  • Vue 官方团队:在 RFC 中明确表示 “v-model 是未来组件通信的核心”

结语:双向绑定,本该如此优雅

Vue3 的 v-model 不是“小改动”,而是对组件通信范式的重新定义

当你能用 v-model:titlev-model:count 一行搞定复杂交互,你就知道——这波升级,值了。

到此这篇关于Vue3中v-model双向绑定的避坑指南(2026最新)的文章就介绍到这了,更多相关Vue3 v-model双向绑定内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 使用vue init webpack项目名创建项目方式

    使用vue init webpack项目名创建项目方式

    这篇文章主要介绍了使用vue init webpack项目名创建项目方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-11-11
  • Vue.js第三天学习笔记(计算属性computed)

    Vue.js第三天学习笔记(计算属性computed)

    这篇文章主要为大家详细介绍了Vue.js第三天的学习笔记,vue.js计算属性computed,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-12-12
  • vue实现加载页面自动触发函数(及异步获取数据)

    vue实现加载页面自动触发函数(及异步获取数据)

    这篇文章主要介绍了vue实现加载页面自动触发函数(及异步获取数据),具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-07-07
  • 在Vue3开发中引用js文件几种常见场景的方法

    在Vue3开发中引用js文件几种常见场景的方法

    在Vue.js开发中,引用外部JavaScript文件是常见的需求,以便利用第三方库或自定义功能,这篇文章主要介绍了在Vue3开发中引用js文件几种常见场景的方法,需要的朋友可以参考下
    2025-08-08
  • vue组件传递对象中实现单向绑定的示例

    vue组件传递对象中实现单向绑定的示例

    下面小编就为大家分享一篇vue组件传递对象中实现单向绑定的示例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-02-02
  • IDEA创建Vue项目的两种方式总结

    IDEA创建Vue项目的两种方式总结

    这篇文章主要介绍了IDEA创建Vue项目的两种方式总结,具有很好的参考价值,希望对大家有所帮助。
    2023-04-04
  • Electron+vue从零开始打造一个本地播放器的方法示例

    Electron+vue从零开始打造一个本地播放器的方法示例

    这篇文章主要介绍了Electron+vue从零开始打造一个本地播放器的方法示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10
  • vue修改数据视图更新原理学习

    vue修改数据视图更新原理学习

    这篇文章主要为大家介绍了vue修改数据视图更新原理学习,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-11-11
  • vue中七牛插件使用的实例代码

    vue中七牛插件使用的实例代码

    本篇文章主要介绍了vue中七牛插件使用,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-07-07
  • vue中多个倒计时实现代码实例

    vue中多个倒计时实现代码实例

    这篇文章主要介绍了vue中多个倒计时实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03

最新评论