欢迎光临白事网
详情描述

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开发&python开源商城二次开发,一站式建站服务
宜春市苹果系统app开发&python开源商城二次开发,一站式建站服务
房产证红本抵押贷款切勿触碰红线,合规使用资金避免法律风险
房产证红本抵押贷款切勿触碰红线,合规使用资金避免法律风险
如何通过参与社区文明养犬宣传活动,来为自己积累正向的养犬信用?
如何通过参与社区文明养犬宣传活动,来为自己积累正向的养犬信用?
在数字经济时代,个人技能与薪酬的绑定关系发生了哪些值得关注的变化?
在数字经济时代,个人技能与薪酬的绑定关系发生了哪些值得关注的变化?
2026年,订阅制服务面临考验,哪些值得保留哪些可以果断取消?
2026年,订阅制服务面临考验,哪些值得保留哪些可以果断取消?
天津市安卓系统app开发#网站建设服务,提供一站式建站服务
天津市安卓系统app开发#网站建设服务,提供一站式建站服务
新乡市殡葬一条龙价格|丧葬灵堂,一年365天
新乡市殡葬一条龙价格|丧葬灵堂,一年365天
2026年不同城市的公积金年度结息政策会有大的差异吗?
2026年不同城市的公积金年度结息政策会有大的差异吗?
丽水市网站SEO优化#网站建设服务公司,优秀设计团队
丽水市网站SEO优化#网站建设服务公司,优秀设计团队
肇庆市精准获客助手&网站搭建服务,优秀开发团队
肇庆市精准获客助手&网站搭建服务,优秀开发团队
安阳市白事服务办理|灵堂守灵,价格透明,1小时上门
安阳市白事服务办理|灵堂守灵,价格透明,1小时上门
在返聘期间,个人是否需要继续自行缴纳社保或购买相关商业保险?
在返聘期间,个人是否需要继续自行缴纳社保或购买相关商业保险?
十堰市殡葬服务热线-白事服务公司,白事出殡服务
十堰市殡葬服务热线-白事服务公司,白事出殡服务