在 Vue 3 中,使用 Composition API 时,如果你尝试直接通过引用(如 formState
)来填充 formList
数组,你会遇到一个问题:所有通过 addForm
方法添加的表单项实际上都是对 formState
的同一个引用。这意呀着,如果你修改了任何一个表单项,所有其他通过 formState
添加的表单项也会同时被修改,因为它们实际上都是指向同一个对象。
为了解决这个问题,你需要在每次调用 addForm
方法时创建一个 formState
的新副本。这可以通过展开操作符(...
)或者使用 Object.assign()
来实现。以下是两种方法的示例:
方法 1: 使用展开操作符
import { reactive, ref } from 'vue';
const formState = reactive({
studentId: undefined,
coachId: undefined,
contractId: undefined,
startDate: '',
startTime: '',
endDate: '',
endTime: '',
memo: '',
});
const formList = ref([]);
const addForm = () => {
// 创建一个 formState 的新副本并添加到 formList 中
formList.value.push({ ...formState });
};
方法 2: 使用 Object.assign()
注意,Object.assign()
会返回目标对象(即新对象),但需要注意的是,如果 formState
中的属性值是对象或数组等引用类型,则这些嵌套对象或数组不会被深拷贝,而只是浅拷贝。对于基本数据类型(如数字、字符串、布尔值等),这种方法是足够的。
const addForm = () => {
// 创建一个 formState 的新副本(浅拷贝)并添加到 formList 中
formList.value.push(Object.assign({}, formState));
};
完整示例
这里是一个完整的示例,展示了如何在 Vue 3 组件中使用上述方法:
<template>
<div>
<button @click="addForm">Add Form</button>
<div v-for="(form, index) in formList" :key="index">
<!-- 渲染表单内容 -->
<p>Student ID: {{ form.studentId }}</p>
<!-- 其他表单字段... -->
<button @click="removeForm(index)">Remove</button>
</div>
</div>
</template>
<script>
import { reactive, ref } from 'vue';
export default {
setup() {
const formState = reactive({
studentId: undefined,
// 其他字段...
});
const formList = ref([]);
const addForm = () => {
formList.value.push({ ...formState });
};
const removeForm = (index) => {
formList.value.splice(index, 1);
};
return { formList, addForm, removeForm };
},
};
</script>
在这个示例中,每次点击“Add Form”按钮时,都会通过 addForm 方法在 formList 中添加一个formState的新副本。这样,每个表单项都是独立的,修改一个表单项不会影响其他表单项。