vue3中在组件上使用v-model

7,403 阅读1分钟

在组件上使用v-model

1、简介

组件上使用v-model的目的也是为了双向绑定,特别是在我们封装高阶表单组件时要实现双向数据绑定时就特别有用。

2、使用

<!-- 父组件 -->
<template>
  <div>
    <child 
    v-model="message"
    @update:model-value="updateMessage"
    ></child>
  </div>
</template>

<script setup>
import { ref } from "@vue/reactivity";
import Child from "./Child.vue";

let message = ref("Hello World Vue3");

const updateMessage = (val) => {
  message.value = val
}
</script>

<!-- 子组件 -->
<template>
  <div>
    <input type="text" v-model="propsMessage">
  </div>
</template>

<script setup>
import { computed } from "@vue/reactivity"

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

let props = defineProps({
  modelValue: String
})

const propsMessage = computed({
  get: () => {
    return props.modelValue
  },
  set: (val) => {
    emmits('update:modelValue', val)
  }
})
</script>
  • 在上面的代码中我们需要注意到2点。 1.其实采用<组件名 v-model="property"></组件名>的写法,这其实是一种语法糖的写法,它等价于<组件名 :model-value="property" @update:modelValue="emitEvent">。 1.在上面的代码中我们采用默认的写法,即v-model="property"的写法,在子组件进行props接受值的时候,其实转为真正的属性就是第一点所转化的:model-value="property",props中定义的值为modelValue

通过以上的介绍,想必我们自身也会产生许多疑问,为什么默认的方法传递为update:modelValue,可以更改这个参数吗,答案是可以的

3、自定义事件名方法传递

<!-- 父组件 -->
<template>
  <div>
    <child 
    v-model:custom="message"
    @update:custom="updateCustom"
    ></child>
    <h1>{{ message }}</h1>
  </div>
</template>

<script setup>
import { ref } from "@vue/reactivity";
import Child from "./Child.vue";

let message = ref("Hello World Vue3");

const updateCustom = (val) => {
  message.value = val
}
</script>

<!-- 子组件 -->
<template>
  <div>
    <input type="text" v-model="propsMessage">
  </div>
</template>

<script setup>
import { computed } from "@vue/reactivity"

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

let props = defineProps({
  custom: String
})

const propsMessage = computed({
  get: () => {
    return props.custom
  },
  set: (val) => {
    emmits('update:custom', val)
  }
})
</script>

通过第三种方式我们可以看出来,自定义的传递名称可以通过v-mode:[variable]的方式来进行修改默认的modelValue的方式。

4、源码解读

我找到了源码中关于这一段的代码。是在定义虚拟DOM节点时,对使用v-model绑定组件,采用transformModel方法进行转化为虚拟DOM节点。在定义事件名称时,有下面一段源码。

  const eventName = arg
    ? isStaticExp(arg)
      ? `onUpdate:${arg.content}`
      : createCompoundExpression(['"onUpdate:" + ', arg])
    : `onUpdate:modelValue`