Vue深入组件:组件 v-model 详解2_vue组件是什么意思

v-model 的参数

默认情况下,组件的 v-model 绑定的是 modelValue prop 和 update:modelValue 事件,但可通过“参数”自定义绑定的 prop 名称,实现更灵活的双向绑定(如多值绑定)。

带参数的 v-model 使用

父组件中,通过 v-model:参数名 指定绑定的 prop 名称:

  <!-- 父组件:绑定到子组件的 title prop -->
  <MyComponent v-model:title="bookTitle" />

其中 bookTitle 是父组件的响应式变量,title 是子组件中自定义的 prop 名称。

子组件适配参数

子组件中,给 defineModel() 传递第一个参数(字符串),指定与参数对应的 prop 名称:

  <!-- MyComponent.vue -->
  <script setup>
  // 声明接收 "title" 参数的模型
  const title = defineModel('title')
  </script>
  
  <template>
    <!-- 输入框与 title 绑定,间接与父组件的 bookTitle 同步 -->
    <input type="text" v-model="title" />
  </template>

此时,父组件的 v-model:title="bookTitle" 会被编译为:

  <MyComponent
    :title="bookTitle" <!-- 传给子组件的 title prop -->
    @update:title="$event => (bookTitle = $event)" <!-- 监听 update:title 事件 -->
  />

若需同时配置 prop 选项(如必填性),在参数后传递选项对象:

  // 声明 title 参数为必填
  const title = defineModel('title', { required: true })

多个 v-model 绑定

结合 v-model 的参数,可在单个组件上绑定多个 v-model,实现多组数据的双向同步。每个 v-model 对应子组件中一个独立的 defineModel() 声明。

父组件使用多个 v-model

父组件通过不同的参数,绑定多个值到子组件:

  <!-- 父组件:分别绑定 first 和 last 到子组件的 first-name 和 last-name -->
  <UserName
    v-model:first-name="first"
    v-model:last-name="last"
  />

其中 firstlast 是父组件中两个独立的响应式变量。

子组件实现多个模型

子组件中,通过 defineModel(参数名) 分别声明对应的模型:

  <!-- UserName.vue -->
  <script setup>
  // 声明 first-name 参数的模型
  const firstName = defineModel('firstName')
  // 声明 last-name 参数的模型
  const lastName = defineModel('lastName')
  </script>
  
  <template>
    <!-- 两个输入框分别绑定两个模型 -->
    <input type="text" v-model="firstName" placeholder="First name" />
    <input type="text" v-model="lastName" placeholder="Last name" />
  </template>

此时:

  • 第一个输入框的变化会通过 firstName 同步到父组件的 first
  • 第二个输入框的变化会通过 lastName 同步到父组件的 last
  • 父组件修改 firstlast 时,对应的输入框也会同步更新。

处理 v-model 修饰符

与原生 input 的 v-model 类似,组件的 v-model 也支持修饰符(如内置的 .trim,或自定义修饰符)。子组件可通过解构 defineModel() 的返回值,获取修饰符并根据修饰符处理值。

基本用法:获取修饰符

父组件给 v-model 添加修饰符(如自定义的 .capitalize,表示首字母大写):

  <!-- 父组件:添加 .capitalize 修饰符 -->
  <MyComponent v-model.capitalize="myText" />

子组件中,通过 [model, modifiers] = defineModel() 解构出修饰符对象(modifiers 是一个对象,键为修饰符名,值为 true):

  <!-- MyComponent.vue -->
  <script setup>
  // 解构出模型和修饰符
  const [model, modifiers] = defineModel()
  
  console.log(modifiers) // { capitalize: true }(父组件添加了该修饰符时)
  </script>
  
  <template>
    <input type="text" v-model="model" />
  </template>

根据修饰符处理值

通过给 defineModel() 传递 getset 选项,可基于修饰符对值进行加工:

  • set(value):当子组件修改模型值时触发,接收原始值,返回处理后的值(会同步到父组件);
  • get(value):当父组件修改值同步到子组件时触发,接收父组件的原始值,返回处理后的值(供子组件使用)。

例如,实现 .capitalize 修饰符(将输入值的首字母转为大写):

 <script setup>
 const [model, modifiers] = defineModel({
   set(value) {
     // 若存在 capitalize 修饰符,处理值
     if (modifiers.capitalize) {
       return value.charAt(0).toUpperCase() + value.slice(1)
     }
     return value // 无修饰符时直接返回原始值
   }
 })
 </script>
 
 <template>
   <input type="text" v-model="model" />
 </template>

此时:

  • 用户在输入框输入“hello”,set 方法会将其转为“Hello”,并同步到父组件的 myText
  • 若父组件直接修改 myText 为“world”,子组件的输入框会显示“World”(因 set 会处理所有值的修改)。

带参数的 v-model 修饰符

若结合参数使用修饰符(如多个 v-model 各有不同修饰符),子组件需为每个模型单独解构修饰符:

 <!-- 父组件:给两个 v-model 分别添加修饰符 -->
 <UserName
   v-model:first-name.capitalize="first"
   v-model:last-name.uppercase="last"
 />

子组件中,每个 defineModel(参数名) 都可解构出对应的修饰符:

 <!-- UserName.vue -->
 <script setup>
 // 解构 first-name 的模型和修饰符
 const [firstName, firstNameModifiers] = defineModel('firstName')
 // 解构 last-name 的模型和修饰符
 const [lastName, lastNameModifiers] = defineModel('lastName')
 
 console.log(firstNameModifiers) // { capitalize: true }
 console.log(lastNameModifiers) // { uppercase: true }
 </script>
 
 <template>
   <input v-model="firstName" placeholder="First name" />
   <input v-model="lastName" placeholder="Last name" />
 </template>

后续可针对 firstNameModifierslastNameModifiers 分别实现修饰符逻辑(如 capitalize 首字母大写、uppercase 全大写)。

总结

组件上的 v-model 是“prop + 事件”的语法糖,核心是实现父子组件的双向数据同步。Vue 3.4+ 的 defineModel() 宏大幅简化了实现流程,无需手动声明 prop 和事件;同时支持参数(多 v-model 绑定)和修饰符(值处理),满足复杂场景需求。

  • 基础用法:子组件 defineModel() 声明模型,父组件 v-model="值" 绑定;
  • 底层机制:基于 modelValue prop 和 update:modelValue 事件;
  • 参数:通过 v-model:参数名 自定义绑定的 prop,子组件 defineModel(参数名) 适配;
  • 修饰符:解构 defineModel() 返回的 modifiers,通过 get/set 选项处理值。
原文链接:,转发请注明来源!