Vue 中自定义组件 v-model 语法的详细解析

以下是 Vue 中自定义组件 v-model 语法的详细解析和具体示例,涵盖 Vue 2 和 Vue 3 的实现差异:


一、v-model 的核心原理

v-model 是语法糖,本质是 属性绑定(Prop) + 事件监听(Event) 的组合,用于实现双向数据绑定。

不同场景下的默认行为:

场景 Vue 2 默认行为 Vue 3 默认行为
原生表单元素 :value + @input :modelValue + @update:modelValue
自定义组件 :value + @input :modelValue + @update:modelValue

二、Vue 2 中的自定义组件 v-model

1. 默认行为
  • 父组件v-model 绑定数据。
  • 子组件 :接收 value prop,通过 input 事件更新数据。

示例:自定义输入组件

vue 复制代码
<!-- 子组件 CustomInput.vue -->
<template>
  <input 
    :value="value" 
    @input="$emit('input', $event.target.value)"
  >
</template>

<script>
export default {
  props: ['value']
};
</script>
vue 复制代码
<!-- 父组件 -->
<template>
  <CustomInput v-model="message" />
  <p>输入内容:{{ message }}</p>
</template>

<script>
export default {
  data() {
    return { message: '' };
  }
};
</script>
2. 自定义 Prop 和事件

通过 model 选项修改默认的 valueinput

vue 复制代码
<!-- 子组件 CustomCheckbox.vue -->
<template>
  <input 
    type="checkbox" 
    :checked="checked" 
    @change="$emit('change', $event.target.checked)"
  >
</template>

<script>
export default {
  model: {
    prop: 'checked',   // 指定绑定的 prop
    event: 'change'    // 指定触发的事件
  },
  props: ['checked']
};
</script>
vue 复制代码
<!-- 父组件 -->
<template>
  <CustomCheckbox v-model="isChecked" />
</template>

三、Vue 3 中的自定义组件 v-model

1. 默认行为
  • 父组件v-model 绑定数据。
  • 子组件 :接收 modelValue prop,通过 update:modelValue 事件更新数据。

示例:自定义输入组件

vue 复制代码
<!-- 子组件 CustomInput.vue -->
<template>
  <input 
    :value="modelValue" 
    @input="$emit('update:modelValue', $event.target.value)"
  >
</template>

<script setup>
defineProps(['modelValue']);
defineEmits(['update:modelValue']);
</script>
vue 复制代码
<!-- 父组件 -->
<template>
  <CustomInput v-model="message" />
  <p>输入内容:{{ message }}</p>
</template>

<script setup>
import { ref } from 'vue';
const message = ref('');
</script>
2. v-model 绑定

Vue 3 支持为单个组件绑定多个 v-model,通过参数区分不同数据。

示例:用户信息表单组件

vue 复制代码
<!-- 子组件 UserForm.vue -->
<template>
  <input 
    :value="username" 
    @input="$emit('update:username', $event.target.value)"
  >
  <input 
    :value="email" 
    @input="$emit('update:email', $event.target.value)"
  >
</template>

<script setup>
defineProps(['username', 'email']);
defineEmits(['update:username', 'update:email']);
</script>
vue 复制代码
<!-- 父组件 -->
<template>
  <UserForm 
    v-model:username="user.name"
    v-model:email="user.email"
  />
  <p>用户名:{{ user.name }}</p>
  <p>邮箱:{{ user.email }}</p>
</template>

<script setup>
import { reactive } from 'vue';
const user = reactive({ name: '', email: '' });
</script>

四、高级用法:自定义修饰符

通过 v-model 的修饰符扩展功能(如自动转大写)。

示例 :自定义输入组件支持 .uppercase 修饰符

vue 复制代码
<!-- 子组件 CustomInput.vue -->
<template>
  <input 
    :value="modelValue" 
    @input="handleInput"
  >
</template>

<script setup>
const props = defineProps({
  modelValue: String,
  modelModifiers: {  // 自动接收修饰符对象
    type: Object,
    default: () => ({})
  }
});

const emit = defineEmits(['update:modelValue']);

const handleInput = (e) => {
  let value = e.target.value;
  if (props.modelModifiers.uppercase) {
    value = value.toUpperCase();
  }
  emit('update:modelValue', value);
};
</script>
vue 复制代码
<!-- 父组件 -->
<template>
  <CustomInput v-model.uppercase="text" />
  <p>大写内容:{{ text }}</p>
</template>

<script setup>
import { ref } from 'vue';
const text = ref('');
</script>

五、Vue 2 与 Vue 3 的对比总结

特性 Vue 2 Vue 3
默认 Prop/事件 value + input modelValue + update:modelValue
v-model 支持 不支持(需用 .sync 支持(v-model:arg
修饰符处理 通过 model 选项配置 通过 modelModifiers 自动接收
语法简洁性 需要额外配置 model 选项 更直观,支持 <script setup>

六、最佳实践

  1. 明确命名 :使用有意义的参数名(如 v-model:username),避免歧义。
  2. 单向数据流:子组件通过事件更新数据,不直接修改 Prop。
  3. 修饰符扩展 :通过 modelModifiers 灵活扩展组件功能。
  4. TypeScript 支持:在 Vue 3 中结合类型定义提升代码健壮性。

通过合理利用 v-model,可以显著简化父子组件间的双向数据绑定逻辑,提升代码可维护性。

相关推荐
xiaoqi92220 分钟前
React Native鸿蒙跨平台如何进行狗狗领养中心,实现基于唯一标识的事件透传方式是移动端列表开发的通用规范
javascript·react native·react.js·ecmascript·harmonyos
jin1233221 小时前
React Native鸿蒙跨平台剧本杀组队消息与快捷入口组件,包含消息列表展示、快捷入口管理、快捷操作触发和消息详情预览四大核心功能
javascript·react native·react.js·ecmascript·harmonyos
烬头88212 小时前
React Native鸿蒙跨平台实现二维码联系人APP(QRCodeContactApp)
javascript·react native·react.js·ecmascript·harmonyos
pas1362 小时前
40-mini-vue 实现三种联合类型
前端·javascript·vue.js
摇滚侠3 小时前
2 小时快速入门 ES6 基础视频教程
前端·ecmascript·es6
2601_949833393 小时前
flutter_for_openharmony口腔护理app实战+预约管理实现
android·javascript·flutter
珑墨3 小时前
【Turbo】使用介绍
前端
军军君014 小时前
Three.js基础功能学习十三:太阳系实例上
前端·javascript·vue.js·学习·3d·前端框架·three
xiaoqi9225 小时前
React Native鸿蒙跨平台如何实现分类页面组件通过searchQuery状态变量管理搜索输入,实现了分类的实时过滤功能
javascript·react native·react.js·ecmascript·harmonyos
打小就很皮...5 小时前
Tesseract.js OCR 中文识别
前端·react.js·ocr