Vue3自定义组件使用v-model

9,931 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第18天,点击查看活动详情

v-model原理

在标签元素上绑定一个v-model,相当于绑定了一个值和一个事件

<input v-model="searchText" />

等同于

<input :value="searchText" @input="searchText = $event.target.value" />

Vue3

在Vue3中,在自定义组件中使用v-model,相当于传递一个 prop 并发出一个事件

<ChildComponent v-model="pageTitle" />

相当于

<ChildComponent :modelValue="pageTitle" @update:modelValue="pageTitle = $event" />

在组件内也必须执行两项操作

  1. 将属性的值modelValue绑定
  2. 触发事件时,发出具有新值的自定义事件input``update:modelValue
// ChildComponent.vue

<template>
    <input :value="modelValue" @input="onChange" /> 
</template>

<script setup>
import { defineProps, defineEmits } from 'vue'

const props = defineProps({
  modelValue: {
    type: XXX,
    required: true
  }
})
const emits = defineEmits(['update:modelValue'])

const onChange = () => {
    emits('update:modelValue', 新值)
}
</script>

v-model参数

默认情况下,使用v-model,相当于传递给组件一个modelValue,如上图所示

我们可以修改这些名称,并将参数传递

<MyComponent v-model:title="bookTitle" />

这时候,组件中需要接收title值和update:title事件

<script setup>
import { defineProps, defineEmits } from 'vue'

const props = defineProps({
  title: {
    type: XXX,
    required: true
  }
})
const emits = defineEmits(['update:title'])
</script>

多个v-model绑定

通过v-model参数的使用,可以在一个组件绑定多个v-model

<UserName v-model:first-name="first" v-model:last-name="last" />
<script setup>
import { defineProps, defineEmits } from 'vue'

const props = defineProps({
  first-name: {
    type: String,
    required: true
  },
  last-name: {
    type: String,
    required: true
  },
})
const emits = defineEmits(['update:first-name','update:last-name'])
</script>

在组件中,不同的场景使用不同的值即可

举个栗子

项目中经常需要使用到弹出框,可以使用v-model来实现一个通用的弹出框模板

首先新建弹出框组件,将来要为他绑定一个v-model,由父组件的一个变量控制弹出框的显示和消失

<template>
  <el-dialog
    :title="$t('msg.excel.roleDialogTitle')"
    :model-value="modelValue"
    @close="closed"
  >
    内容

    <template #footer>
      <span class="dialog-footer">
        <el-button @click="closed">取消</el-button>
        <el-button type="primary" @click="onConfirm">确定</el-button>
      </span>
    </template>
  </el-dialog>
</template>

<script setup>
import { defineProps, defineEmits } from 'vue'
defineProps({
  modelValue: {
    type: Boolean,
    required: true
  }
})
const emits = defineEmits(['update:modelValue'])

/**
  确定按钮点击事件
 */
const onConfirm = () => {
  closed()
}

/**
 * 关闭
 */
const closed = () => {
  emits('update:modelValue', false)
}
</script>

在父组件中引入弹出框,使用v-model绑定一个布尔值

···
<distribute-permission
      v-model="distributePermissionVisible"
></distribute-permission>
···

import DistributePermission from './components/DistributePermission.vue'

const distributePermissionVisible = ref(false)

这里是点击按钮出现弹出框,在父组件绑定点击事件

···
<el-button
    type="primary"
    size="mini"
    @click="onDistributePermissionClick(row)"
  >
    {{ $t('msg.role.assignPermissions') }}
</el-button>
···

const onDistributePermissionClick = row => {
  distributePermissionVisible.value = true
}