vue3 绑定多个model技巧之 抽取useVModel
test.vue
<template> <div :class="$style.container"> <Form v-model:name="form.name" v-model:surname="form.surname" @submit="onSubmit" /> {{form.name}} {{form.surname}} </div> </template> <script> import { ref } from 'vue' import Form from '@/components/Form.vue' export default { components: { Form, }, setup() { const form = ref({ name: '', surname: '', }) const onSubmit = () => console.log(form) return { form, onSubmit, } }, } </script> <style module> .container { max-width: 30rem; @apply mx-auto py-8; } </style>
form.vue
<template> <form @submit.prevent="$emit('submit')"> <div :class="$style.formBlock"> <label :class="$style.label">Name</label> <input v-model="nameState" :class="$style.input" type="text" aria-label="Name input" /> </div> <div :class="$style.formBlock"> <label :class="$style.label">Surname</label> <input v-model="surnameState" :class="$style.input" type="text" aria-label="Surname input" /> </div> <div> <button class="float-right bg-blue-100 text-blue-900 px-4 py-3 rounded font-semibold" type="submit" > Submit </button> </div> </form> </template> <script> import { useVModel } from './useVModel.js' export default { emits: ['update:name', 'update:surname', 'submit'], props: { name: String, surname: String, }, setup(props) { return { nameState: useVModel(props, 'name'), surnameState: useVModel(props, 'surname'), } }, } </script> <style module> .formBlock { @apply flex flex-col mb-4; } .label { @apply mb-2; } .input { @apply px-4 py-3 shadow rounded border border-gray-300 bg-white; } </style>
重点来了抽取
useVModel.js
import { computed, getCurrentInstance } from 'vue' export const useVModel = (props, propName) => { const vm = getCurrentInstance().proxy return computed({ get() { return props[propName] }, set(value) { vm.$emit(`update:${propName}`, value) }, }) }
亲测效果如下