v-model 参数用法

Vue 3 中 v-model 参数和多个 v-model 绑定的使用方法

问题

Vue 3 中 v-model 参数是什么?如何使用?

解答

基本概念

Vue 3 中,v-model 支持参数语法,允许自定义绑定的 prop 名称:

<!-- 父组件 -->
<template>
  <!-- v-model:title 绑定 title prop -->
  <MyInput v-model:title="bookTitle" />
  
  <!-- 等价于 -->
  <MyInput :title="bookTitle" @update:title="bookTitle = $event" />
</template>

子组件实现

<!-- MyInput.vue -->
<script setup>
// 定义 title prop 和 update:title 事件
defineProps(['title'])
defineEmits(['update:title'])
</script>

<template>
  <input
    :value="title"
    @input="$emit('update:title', $event.target.value)"
  />
</template>

多个 v-model 绑定

v-model 参数的最大优势是支持多个双向绑定:

<!-- 父组件 -->
<template>
  <UserForm
    v-model:name="userName"
    v-model:email="userEmail"
    v-model:age="userAge"
  />
</template>

<script setup>
import { ref } from 'vue'

const userName = ref('张三')
const userEmail = ref('zhangsan@example.com')
const userAge = ref(25)
</script>
<!-- UserForm.vue -->
<script setup>
defineProps(['name', 'email', 'age'])
defineEmits(['update:name', 'update:email', 'update:age'])
</script>

<template>
  <form>
    <input
      :value="name"
      @input="$emit('update:name', $event.target.value)"
      placeholder="姓名"
    />
    <input
      :value="email"
      @input="$emit('update:email', $event.target.value)"
      placeholder="邮箱"
    />
    <input
      type="number"
      :value="age"
      @input="$emit('update:age', Number($event.target.value))"
      placeholder="年龄"
    />
  </form>
</template>

使用 defineModel(Vue 3.4+)

Vue 3.4 引入了 defineModel 宏,简化写法:

<!-- UserForm.vue -->
<script setup>
// 自动处理 prop 和 emit
const name = defineModel('name')
const email = defineModel('email')
const age = defineModel('age', { type: Number })
</script>

<template>
  <form>
    <input v-model="name" placeholder="姓名" />
    <input v-model="email" placeholder="邮箱" />
    <input type="number" v-model="age" placeholder="年龄" />
  </form>
</template>

Vue 2 vs Vue 3 对比

<!-- Vue 2:只能有一个 v-model -->
<MyComponent v-model="value" />
<!-- 绑定 value prop + input 事件 -->

<!-- Vue 3:默认 v-model -->
<MyComponent v-model="value" />
<!-- 绑定 modelValue prop + update:modelValue 事件 -->

<!-- Vue 3:带参数的 v-model -->
<MyComponent v-model:title="title" />
<!-- 绑定 title prop + update:title 事件 -->

关键点

  • v-model:xxx 绑定名为 xxx 的 prop,触发 update:xxx 事件
  • 一个组件可以有多个 v-model 绑定,解决了 Vue 2 只能有一个 v-model 的限制
  • Vue 3.4+ 使用 defineModel('xxx') 可以大幅简化代码
  • 默认 v-model 等价于 v-model:modelValue