观语AI2026
24.3MB · 2026-04-03
你的表单数据绑定了却不动?自定义组件 v-model 写了就是不生效?
而用 Vue3 正确的 v-model 写法,一行代码搞定双向绑定,支持多字段同步、自定义事件、TS 完美兼容——再也不用手动写 $emit('input') 或 .sync 修饰符!
如果你受够了:
v-model 突然失效:value + @input,有人写 v-model,代码风格混乱那么,这篇 2026 年最新实操指南,就是为你写的——
不用翻文档,所有代码模板直接复制粘贴,今天就能写出零 bug 的双向绑定!
很多从 Vue2 过来的开发者,还在用老思维写 v-model,结果频频翻车。
Vue3 对 v-model 做了三大升级:
| 特性 | Vue2 | Vue3 |
|---|---|---|
| 绑定属性 | 固定为 value | 可自定义(如 title、count) |
| 触发事件 | input | 统一为 update:xxx |
| 多绑定支持 | 不支持 | 一个组件可绑多个 v-model |
| 语法糖 | 需配合 .sync | 原生支持,无需额外修饰符 |
适用于 <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 }}<br/>
密码:{{ password }}<br/>
简介:{{ bio }}<br/>
已同意:{{ 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。
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>
<template>
<MyInput v-model="customText" />
<p>输入内容:{{ customText }}</p>
</template>
<script setup>
import { ref } from 'vue'
import MyInput from './MyInput.vue'
const customText = ref('')
</script>
一个组件同时绑定多个双向数据,比如姓名 + 年龄 + 邮箱。
<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>
// 错误
let text = '' // 普通变量
// v-model="text" → 修改无效!
// 正确
const text = ref('') // 响应式
// 错误(Vue2 写法)
defineProps(['value'])
defineEmits(['input'])
// 正确(Vue3 标准)
defineProps(['modelValue'])
defineEmits(['update:modelValue'])
v-model 和 :value 混用<!-- 错误 -->
<input v-model="msg" :value="defaultValue" />
<!-- 正确 -->
<input v-model="msg" />
<!-- 或初始化时:const msg = ref(defaultValue) -->
// 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>
v-model 模式v-model:content 实时同步v-modelv-model 是未来组件通信的核心”Vue3 的 v-model 不是“小改动”,而是对组件通信范式的重新定义。
当你能用 v-model:title、v-model:count 一行搞定复杂交互,你就知道——这波升级,值了。
各位互联网搭子,要是这篇文章成功引起了你的注意,别犹豫,关注、点赞、评论、分享走一波,让我们把这份默契延续下去,一起在知识的海洋里乘风破浪!