汕尾市文章资讯

vue3 update:modelValue用法小结

2026-03-25 14:15:02 浏览次数:1
详细信息

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 机制提供了灵活的双向数据绑定:

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

相关推荐