欢迎光临白事网
详情描述

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年农村医保个人缴费上涨后,对应的报销福利有哪些提升?
2026年,用手机扫描产品上的追溯码,能查看到哪些具体信息?
2026年,用手机扫描产品上的追溯码,能查看到哪些具体信息?
循环用水、一水多用等家庭水循环理念具体如何操作与实践?
循环用水、一水多用等家庭水循环理念具体如何操作与实践?
汕尾市AI数字人制作小视频#企业网站建设公司,专业开发团队
汕尾市AI数字人制作小视频#企业网站建设公司,专业开发团队
对于不熟悉智能手机的老年人,2026年的政务服务有哪些线下便捷通道?
对于不熟悉智能手机的老年人,2026年的政务服务有哪些线下便捷通道?
天津市丧事一站式服务|白事入殓服务,为家属解决后顾之忧
天津市丧事一站式服务|白事入殓服务,为家属解决后顾之忧
夏季高温或冬季严寒等极端天气,对宠物托运计划会产生哪些具体影响?
夏季高温或冬季严寒等极端天气,对宠物托运计划会产生哪些具体影响?
外嫁女与兄弟在宅基地继承上发生纠纷,法律通常会如何裁决?
外嫁女与兄弟在宅基地继承上发生纠纷,法律通常会如何裁决?
北京市丧葬服务公司|殡葬悼念会布置,收费透明,1小时上门
北京市丧葬服务公司|殡葬悼念会布置,收费透明,1小时上门
绥化市苹果app开发#网站设计正规公司,收费标准
绥化市苹果app开发#网站设计正规公司,收费标准
秦皇岛市精准获客引流&java开源商城二次开发,定制开发
秦皇岛市精准获客引流&java开源商城二次开发,定制开发
从进化的角度看,为什么人类久坐会带来这么多健康问题与不适?
从进化的角度看,为什么人类久坐会带来这么多健康问题与不适?
比较消费券与现金补贴,哪种方式更能有效刺激社会总体消费需求?
比较消费券与现金补贴,哪种方式更能有效刺激社会总体消费需求?
宣城市殡葬一条龙公司-丧葬一站式服务,丧葬灵棚策划
宣城市殡葬一条龙公司-丧葬一站式服务,丧葬灵棚策划
在缴费阶段,个人养老金账户如何帮助我们合理减少当年的个人所得税负担?
在缴费阶段,个人养老金账户如何帮助我们合理减少当年的个人所得税负担?
如果生物识别模板数据泄露,会比密码泄露更严重吗?2026年我们该如何防范?
如果生物识别模板数据泄露,会比密码泄露更严重吗?2026年我们该如何防范?
在气候变化背景下,未来“超级台风”或“极端暴雨”的破坏力会更强吗?
在气候变化背景下,未来“超级台风”或“极端暴雨”的破坏力会更强吗?
从经济学视角看,家庭内部的无偿照护工作创造了哪些难以估量的社会价值?
从经济学视角看,家庭内部的无偿照护工作创造了哪些难以估量的社会价值?
日常通勤中频繁使用人脸识别门禁,怎样的穿着既得体又便于快速通过?
日常通勤中频繁使用人脸识别门禁,怎样的穿着既得体又便于快速通过?
瓦房店市AI数字人直播带货#b2b网站开发,高端网站开发设计
瓦房店市AI数字人直播带货#b2b网站开发,高端网站开发设计