vue2 vue3 uniapp (微信小程序) v-model双向绑定
一、核心概念
-
Vue2:基于 value 属性和 input 事件,需手动实现多绑定。 -
Vue3:重构 v-model,支持多参数和自定义属性/事件,灵活度更高。 -
uni-app(微信小程序):兼容 Vue 语法,受小程序原生限制,部分细节不同。
二、分场景详细用法与实例
1. 基础 v-model(单值绑定)
(1)Vue2
-
逻辑:v-model=”val” 等价于 :value=”val” @input=”val = $event.target.value” -
自定义组件需接收 value 属性,触发 input 事件
<!-- 父组件 --><template><Childv-model="msg" /></template><script>import Child from './Child.vue'export default {components: { Child },data() {return { msg: 'Vue2 基础绑定' }}}</script><!-- 子组件 Child.vue --><template><input:value="value" @input="$emit('input', $event.target.value)" /></template><script>export default {props: {value: { type: String, default: '' }}}</script>
(2)Vue3
-
逻辑:v-model=”val” 等价于 :modelValue=”val” @update:modelValue=”val = $event” -
自定义组件更简洁
<!-- 父组件 --><template><Childv-model="msg" /></template><scriptsetup>import Child from './Child.vue'import { ref } from 'vue'const msg = ref('Vue3 基础绑定')</script><!-- 子组件 Child.vue --><template><input:value="modelValue" @input="$emit('update:modelValue', $event.target.value)" /></template><scriptsetup>defineProps(['modelValue'])defineEmits(['update:modelValue'])</script>
(3)uni-app(微信小程序)
-
兼容 Vue2 语法(默认基于 Vue2,Vue3 需单独配置) -
原生组件事件参数在 detail,自定义组件遵循 Vue 规则
<!-- 父组件(pages/index/index.vue) --><template><view><Childv-model="msg" /><inputv-model="nativeMsg"placeholder="原生输入框" /></view></template><script>export default {data() {return { msg: 'uni-app 绑定', nativeMsg: '' }},components: {Child: import('@/components/Child.vue')}}</script><!-- 子组件(components/Child.vue) --><template><input:value="value" @input="$emit('input', $event.detail.value)" /></template><script>export default {props: { value: String }}</script>
2. 多 v-model(多值双向绑定)
(1)Vue2(手动实现)
<!-- 父组件 --><template><Child:name="name" @update:name="name = $event":age="age" @update:age="age = $event"/></template><script>export default {data() {return { name: '张三', age: 20 }}}</script><!-- 子组件 --><template><input:value="name" @input="$emit('update:name', $event.target.value)" /><inputtype="number":value="age" @input="$emit('update:age', $event.target.value)" /></template><script>export default {props: { name: String, age: Number }}</script>
(2)Vue3(原生支持多 v-model)
-
通过 v-model:参数名 实现,无需手动写事件
<!-- 父组件 --><template><Childv-model:name="name"v-model:age="age"/></template><scriptsetup>import Child from './Child.vue'import { ref } from 'vue'const name = ref('张三')const age = ref(20)</script><!-- 子组件 --><template><input:value="name" @input="$emit('update:name', $event.target.value)" /><inputtype="number":value="age" @input="$emit('update:age', $event.target.value)" /></template><scriptsetup>defineProps(['name', 'age'])defineEmits(['update:name', 'update:age'])</script>
(3)uni-app(微信小程序)
-
Vue2 版本同 Vue2 手动实现 -
Vue3 版本兼容多 v-model,注意事件参数格式
<!-- uni-app Vue3 子组件 --><template><input:value="name" @input="$emit('update:name', $event.detail.value)" /><inputtype="number":value="age" @input="$emit('update:age', $event.detail.value)" /></template><scriptsetup>defineProps(['name', 'age'])defineEmits(['update:name', 'update:age'])</script>
3. 自定义属性与事件双向绑定
<!-- 父组件 --><template><Childv-model:user="user" /></template><scriptsetup>import Child from './Child.vue'import { ref } from 'vue'const user = ref({ name: '李四', phone: '13800138000' })</script><!-- 子组件 --><template><input:value="user.name"@input="updateUser('name', $event.target.value)"/><input:value="user.phone"@input="updateUser('phone', $event.target.value)"/></template><scriptsetup>const props = defineProps(['user'])const emit = defineEmits(['update:user'])const updateUser = (key, val) => {const newUser = { ...props.user, [key]: val }emit('update:user', newUser)}</script>
-
避免使用小程序原生事件名(如 tap、change)作为自定义事件名,防止冲突。 -
复杂数据建议通过事件更新,不直接绑定到原生组件属性。
三、关键区别汇总表
|
特性 |
Vue2 |
Vue3 |
uni-app(微信小程序) |
|
基础 v-model 底层 |
value + input 事件 |
modelValue + update:modelValue |
兼容 Vue2(value + input),原生组件参数在 detail |
|
多 v-model |
手动绑定:属性 + @事件 |
原生支持 v-model: 参数名 |
Vue2 版本手动绑定,Vue3 版本兼容 |
|
自定义属性声明 |
props 选项 |
defineProps 宏 |
同对应 Vue 版本 |
|
自定义事件声明 |
无强制声明,直接 $emit |
defineEmits 宏(推荐) |
同对应 Vue 版本,避免原生事件名 |
|
复杂数据绑定 |
支持,但需注意引用类型修改 |
支持,推荐创建新对象 / 数组 |
支持,但避免绑定到原生组件属性 |
四、总结与最佳实践
关键点回顾
-
基础绑定差异:Vue2 用 value/input,Vue3 用 modelValue/update:modelValue,uni-app 原生事件参数在 detail。 -
多 v-model:Vue3 原生支持 v-model:参数名,Vue2/uni-app Vue2 需手动实现。 -
自定义绑定核心:本质是父传子(props)+ 子通知父(emit),不要直接修改 props。
最佳实践建议
-
优先使用框架原生 v-model 语法,减少手动代码。 -
uni-app 区分原生组件与自定义组件的事件参数格式。 -
绑定复杂数据时,使用新对象(如解构),避免直接修改 props,确保数据流规范。
夜雨聆风
