欢迎光临白事网
详情描述

update:modelValue 是用于实现自定义组件双向数据绑定的核心机制。以下是它的用法小结:

1. 基础用法

组件定义

<!-- MyInput.vue -->
<script setup>
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])

const handleInput = (e) => {
  emit('update:modelValue', e.target.value)
}
</script>

<template>
  <input :value="modelValue" @input="handleInput" />
</template>

组件使用

<template>
  <MyInput v-model="text" />
  <!-- 等价于 -->
  <MyInput :modelValue="text" @update:modelValue="text = $event" />
</template>

2. 使用 defineModel() (Vue 3.4+ 推荐)

Vue 3.4 引入了 defineModel(),简化了双向绑定的实现:

<!-- MyInput.vue -->
<script setup>
// 自动处理 props 和 emits
const model = defineModel()

// 如果需要类型检查
const model = defineModel<string>() // 指定类型
const model = defineModel({ type: String, default: '' }) // 带选项
</script>

<template>
  <input v-model="model" />
</template>

3. 多个 v-model

组件定义

<!-- UserForm.vue -->
<script setup>
defineProps({
  firstName: String,
  lastName: String,
  age: Number
})

defineEmits(['update:firstName', 'update:lastName', 'update:age'])
</script>

<template>
  <input 
    :value="firstName" 
    @input="$emit('update:firstName', $event.target.value)" 
  />
  <input 
    :value="lastName" 
    @input="$emit('update:lastName', $event.target.value)" 
  />
  <input 
    type="number"
    :value="age" 
    @input="$emit('update:age', parseInt($event.target.value) || 0)" 
  />
</template>

组件使用

<template>
  <UserForm 
    v-model:firstName="firstName"
    v-model:lastName="lastName"
    v-model:age="age"
  />
</template>

4. 使用 defineModel() 处理多个 v-model

<!-- UserForm.vue -->
<script setup>
const firstName = defineModel('firstName')
const lastName = defineModel('lastName')
const age = defineModel('age', { type: Number, default: 0 })
</script>

<template>
  <input v-model="firstName" />
  <input v-model="lastName" />
  <input v-model="age" type="number" />
</template>

5. 带修饰符的 v-model

组件定义

<!-- MyInput.vue -->
<script setup>
const [model, modifiers] = defineModel({
  // 处理修饰符
  set(value) {
    if (modifiers.trim) {
      return value.trim()
    }
    if (modifiers.uppercase) {
      return value.toUpperCase()
    }
    return value
  }
})
</script>

<template>
  <input v-model="model" />
</template>

组件使用

<template>
  <MyInput v-model.trim="text" />
  <MyInput v-model.uppercase="text" />
</template>

6. 复杂数据类型处理

<!-- ObjectPicker.vue -->
<script setup>
const props = defineProps({
  modelValue: {
    type: Object,
    default: () => ({})
  }
})

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

const updateField = (key, value) => {
  emit('update:modelValue', {
    ...props.modelValue,
    [key]: value
  })
}
</script>

7. 最佳实践和注意事项

推荐做法:

使用 defineModel():Vue 3.4+ 优先使用,代码更简洁 明确类型定义:为 props 提供明确的类型定义 保持响应性:确保 emit 的值是响应式的 处理默认值:为可选的 modelValue 提供合适的默认值

常见问题:

<!-- ❌ 错误:直接修改 props -->
<script setup>
const props = defineProps(['modelValue'])
const handleInput = (e) => {
  props.modelValue = e.target.value // 错误!
}
</script>

<!-- ✅ 正确:使用 emit -->
<script setup>
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])

const handleInput = (e) => {
  emit('update:modelValue', e.target.value)
}
</script>

8. TypeScript 支持

<!-- MyInput.vue -->
<script setup lang="ts">
// 使用 defineModel
const model = defineModel<string>()

// 或者使用完整的 props/emits 定义
interface Props {
  modelValue: string
}

interface Emits {
  (e: 'update:modelValue', value: string): void
}

const props = defineProps<Props>()
const emit = defineEmits<Emits>()
</script>

总结

Vue 3 的 update:modelValue 机制提供了灵活的双向数据绑定:

  • 基础模式:使用 props + emit
  • 简化模式:Vue 3.4+ 使用 defineModel()
  • 支持多个 v-model
  • 支持修饰符
  • 良好的 TypeScript 支持

根据项目需求和 Vue 版本选择合适的实现方式。

相关帖子
银行房产抵押贷款利率政策调整,下半年走势分析与预测
银行房产抵押贷款利率政策调整,下半年走势分析与预测
2026年关于预付式消费有没有出新规定,消费者维权是不是比以前更容易了?
2026年关于预付式消费有没有出新规定,消费者维权是不是比以前更容易了?
00后把川话玩成说唱炸场效果,方言是不是早就不只是爷爷奶奶的语言了?
00后把川话玩成说唱炸场效果,方言是不是早就不只是爷爷奶奶的语言了?
绿色健康饮食趋势下,如何通过焯水减少肉类中多余的油脂摄入?
绿色健康饮食趋势下,如何通过焯水减少肉类中多余的油脂摄入?
2026年农村医保个人缴费上涨后,对应的报销福利有哪些提升?
2026年农村医保个人缴费上涨后,对应的报销福利有哪些提升?
2026年,用手机扫描产品上的追溯码,能查看到哪些具体信息?
2026年,用手机扫描产品上的追溯码,能查看到哪些具体信息?
小区房子抵押贷款征信要求商业银行是什么?商业银行征信标准
小区房子抵押贷款征信要求商业银行是什么?商业银行征信标准
过桥业务结清全套流程,讲解对账、销户、领取凭证等收尾手续
过桥业务结清全套流程,讲解对账、销户、领取凭证等收尾手续
厦门市安卓app开发#品牌网站开发,提供一站式建站服务
厦门市安卓app开发#品牌网站开发,提供一站式建站服务
濮阳市短视频营销推广&网站开发建设,一站式建站服务
濮阳市短视频营销推广&网站开发建设,一站式建站服务
莆田市白事一站式服务|净身穿衣,24小时服务热线
莆田市白事一站式服务|净身穿衣,24小时服务热线
六盘水殡葬一条龙公司电话-办理丧事,葬礼服务
六盘水殡葬一条龙公司电话-办理丧事,葬礼服务
互联网平台汽车抵押贷款条件,全流程线上申请需要什么条件?
互联网平台汽车抵押贷款条件,全流程线上申请需要什么条件?
宁德市殡葬一条龙服务|殡葬灵棚布置,安全快捷
宁德市殡葬一条龙服务|殡葬灵棚布置,安全快捷
学历高低影响信用贷款额度?教育背景对小额信用贷的影响
学历高低影响信用贷款额度?教育背景对小额信用贷的影响
渭南市殡葬一条龙-白事一站式服务,葬礼花篮
渭南市殡葬一条龙-白事一站式服务,葬礼花篮
退货时使用非商家指定的快递公司,产生的运费差价或问题由谁负责?
退货时使用非商家指定的快递公司,产生的运费差价或问题由谁负责?
2026年,主流外卖平台的食品安全保险或理赔机制是否覆盖了异物问题?
2026年,主流外卖平台的食品安全保险或理赔机制是否覆盖了异物问题?
兰州市精准获客渠道#网站搭建服务,收费透明
兰州市精准获客渠道#网站搭建服务,收费透明
红河短视频推广&网站定制,服务可靠
红河短视频推广&网站定制,服务可靠
吕梁市定制化网站开发#专业网站建设设计,专业建站公司
吕梁市定制化网站开发#专业网站建设设计,专业建站公司