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,可以显著简化父子组件间的双向数据绑定逻辑,提升代码可维护性。

相关推荐
小二·8 分钟前
如何在Vue项目中封装axios
前端·javascript·vue.js
Billy Qin21 分钟前
【Mac】npm error Error: EACCES: permission denied, mkdir‘/Users/...
前端·macos·npm
好青崧37 分钟前
HTML元素小卖部:表单元素 vs 表格元素选购指南
前端
计算机-秋大田40 分钟前
基于Spring Boot的戒烟网站的设计与实现(LW+源码+讲解)
java·vue.js·spring boot·后端·课程设计
饼干帅成渣1 小时前
HTML跑酷
前端·html
绿草在线1 小时前
elementplus的el-tabs路由式
前端·javascript·vue.js
知识分享小能手1 小时前
CSS3学习教程,从入门到精通, CSS3 盒子模型的详细语法知识点及案例代码(23)
前端·javascript·css·学习·css3·html5·java后端开发
Gerry-Xu1 小时前
鸿蒙篇:vp、fp、px
前端·javascript·css
东东__net1 小时前
26_ajax
前端·javascript·ajax
Riesenzahn1 小时前
怎么把项目里的webpack换成vite?
前端·javascript