问题:
假设现在你有5个类别的表单,每个表单都有几个公有属性,比如姓名,编号,时间等,除此之外每个类别都有其他几个私有属性,需要把公有的属性提取出来,之后整合字段数据提交表单。
具体实现方式如下:
在共有组件中,使用 reactive 函数创建一个响应式的 commonData 对象,将共有属性加入到该对象中。然后,将 commonData 对象、handleSubmit 方法和 slot 作为组件返回值,供子组件进行引入。
在子组件中,先使用 ref 函数创建一个响应式的选项对象 formData,将子组件的独有属性加入到该对象中。然后,在子组件模板中使用 v-model 绑定到 formData 对象中相应的属性上,并在 submitForm 方法中将 formData 对象和 commonData 对象使用对象浅合并的方式整合后,调用 handleSubmit 方法,将整合后的数据传递给共有组件的处理方法。
下面是示例代码:
(1)最外层组件:Demo.vue
<template>
<Father>
<FoodForm />
</Father>
</template>
<script>
import { defineComponent, inject, provide, ref } from 'vue'
import Father from './Father.vue'
import FoodForm from './FootForm.vue'
export default defineComponent({
components: {
Father,
FoodForm
},
setup(props, { slots }) {
return {}
}
})
</script>
(2)公有属性组件-Father.vue
<template>
<div>
<div class="line-table">
<label for="username">姓名:</label>
<input type="text" id="username" v-model="commonData.userName" />
</div>
<div>
<label for="id">编号:</label>
<input type="text" id="id" v-model="commonData.id" />
</div>
<div>
<label for="time">时间:</label>
<input type="text" id="time" v-model="commonData.time" />
</div>
<!-- 插槽,用来放置子组件 -->
<slot></slot>
</div>
</template>
<script >
import { getCurrentInstance, defineComponent, provide, ref } from "vue";
import useFormComposable from "./formComposable";
export default defineComponent({
setup() {
const { commonData, handleSubmit } = useFormComposable();
const slots = getCurrentInstance().slots;
provide('Father', { handleSubmit })
return {
commonData,
handleSubmit,
slots,
};
},
})
</script>
<style scoped>
.line-table {
display: flex;
align-items: center;
}
</style>
formComposable.js
import { reactive } from 'vue'
export default function useFormComposable() {
const commonData = reactive({
userName: '',
id: '',
time: ''
})
const handleSubmit = data => {
const formData = Object.assign(commonData, data)
console.log('~~~11~~~整合数据', formData)
}
return {
commonData,
handleSubmit
}
}
(3)子组件-私有属性组件-FootForm.vue
<template>
<div>
<div>
<label for="foodName">食品名称:</label>
<input type="text" id="foodName" v-model="formData.foodName" />
</div>
<div>
<label for="foodSize">食品大小:</label>
<input type="text" id="foodSize" v-model="formData.foodSize" />
</div>
<button @click.prevent="submitForm">提交</button>
</div>
</template>
<script>
import { defineComponent, ref, inject } from 'vue'
export default defineComponent({
setup(props, { slots }) {
const formData = ref({
foodName: '',
foodSize: ''
})
const { handleSubmit } = inject('Father')
const submitForm = () => {
handleSubmit(formData.value)
}
return {
formData,
submitForm
}
}
})
</script>
(4)子组件2-私有属性组件-ProductForm.vue
<!-- 子组件2 -->
<template>
<div>
<div>
<label for="foodName">食品名称:</label>
<input type="text" id="foodName" v-model="formData.foodName" />
</div>
<div>
<label for="foodSize">食品大小:</label>
<input type="text" id="foodSize" v-model="formData.foodSize" />
</div>
<button @click.prevent="submitForm">提交</button>
</div>
</template>
<script>
import { defineComponent, ref, inject } from 'vue'
export default defineComponent({
setup(props, { slots }) {
const formData = ref({
foodName: '',
foodSize: ''
})
const { handleSubmit } = inject('Father')
const submitForm = () => {
handleSubmit(formData.value)
}
return {
formData,
submitForm
}
}
})
</script>