Skip to content
封装子组件的v-model双向绑定

单个v-model

父组件

html
<template>
  <!-- 就像用普通 input -->
  <MyInput v-model="text" />
  <p>父组件:{{ text }}</p>
</template>

<script setup>
import { ref } from 'vue'
const text = ref('hello')
</script>

子组件

js
<template>
  <input
    :value="modelValue"
    @input="onInput"
  />
</template>

<script setup>
// 1. 声明接收
const props = defineProps({
  modelValue: String
})

// 2. 声明事件
const emit = defineEmits(['update:modelValue'])

function onInput(e) {
  // 3. 抛新值
  emit('update:modelValue', e.target.value)
}
</script>

多个v-model

父组件

js
<template>
  <UserCard
    v-model:name="name"
    v-model:age="age"
  />
  <p>name:{{ name }}  age:{{ age }}</p>
</template>

<script setup>
import { ref } from 'vue'
const name = ref('Tom')
const age  = ref(18)
</script>

子组件

js
<template>
  <input :value="name" @input="e=>$emit('update:name',e.target.value)" />
  <input :value="age"  @input="e=>$emit('update:age', e.target.value)" />
</template>

<script setup>
defineProps({
  name: String,
  age: [String, Number]
})
</script>

带.lazy/.number等修饰符的的v-model

父组件

js
<template>
  <MyInput v-model.number="num" placeholder="输入自动变 number" />
  <p>num 值:{{ num }}(类型:{{ typeof num }})</p>
</template>

<script setup>
import { ref } from 'vue'
const text = ref('abc')
const num  = ref(0)
</script>

子组件

js
<script setup>
const props = defineProps({
  modelValue: [String, Number],
  modelModifiers: { default: () => ({}) } // 接收修饰符
})

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

function onInput(e) {
  let val = e.target.value
  if (props.modelModifiers.number) {
    val = Number(val)          // .number 自动转数值
  }
  emit('update:modelValue', val)
}
</script>