我正在开发 Vue.js 应用程序,并遇到了一个问题,即在父组件中修改时,列表中的任务(提交)不会响应式更新。我有一个更新任务数组的 SubmissionWrapper 组件,但如果没有外部触发器,这些更改不会反映在 SubmissionInfo 或 SubmissionTask 组件中。
这是代码的简化版本:
提交包装
<template>
# Other template code
<GraderSubmissionInfo
v-for="(submission, index) in submissions"
:key="index"
:submission
/>
</template>
<script setup>
import { ref } from 'vue';
let submissions = ref([]);
let isCreatingSubmission = ref(false);
async function createSubmission() {
if (isCreatingSubmission.value) return;
isCreatingSubmission.value = true;
let taskCount = Math.floor(Math.random() * 10) + 1;
let tasks = Array.from({ length: taskCount }, (_, index) => ({
status: 'undf',
title: `Task ${index + 1}`,
scoreEarned: 0,
scoreTotal: 20,
notes: `Notes for Task ${index + 1}`,
}));
let submission = {
title: 'Attempt',
scoreEarned: 0,
scoreTotal: 20,
submissionTime: new Date().toUTCString(),
duration: 503,
status: 'undf',
tasks,
};
submissions.value.unshift(submission);
for (let i = 0; i < tasks.length; i++) {
await new Promise(resolve => setTimeout(resolve, 1000 + Math.random() * 10));
tasks[i].status = Math.random() > 0.5 ? 'pass' : 'fail';
tasks[i].notes = 'updated';
submissions.value[0].tasks = [...tasks];
}
isCreatingSubmission.value = false;
}
</script>
提交信息
<template>
<div>
<div>
<GraderSubmissionTask
v-for="(task, index) in submission.tasks"
:key="index"
:task="task"
/>
</div>
</div>
</template>
提交任务
<template>
<div class="bg-secondary px-8 py-2 flex flex-row items-center justify-between font-mono">
<div class="flex w-[50%] items-center">
<div class="pr-8">
<component
:is="activeComponent"
/>
</div>
<div class="">
{{ task.title }}
</div>
</div>
<div class="w-[25%]">
{{ task.scoreEarned }} /{{ task.scoreTotal }}
</div>
<div class="w-[25%]">
{{ task.notes }}
</div>
</div>
</template>
<script setup>
import { defineProps } from 'vue'
const props = defineProps({
task: Object
})
const stateComponents = [
'Progress',
'Failed',
'Success'
]
let activeComponentKey = ref(stateComponents[2])
const activeComponent = computed(() => {
return defineAsyncComponent(() => import(`~/components/Icons/Small/${activeComponentKey.value}.vue`))
})
</script>
问题:
任何帮助或见解将不胜感激
key,应该避免(它实际上与根本不使用键相同)。 如果对于 <GraderSubmissionTask>
v-for 您使用
:key="task.notes"
,它应该工作得更好,因此当注释属性发生突变时,会检测到差异并重新渲染节点。
<GraderSubmissionTask
v-for="task in submission.tasks"
:key="task.notes"
:task="task"
/>
如果您计划更改任务之外的其他属性,则需要确保 SubmissionWrapper 组件中的 v-for 键也比索引更好。键必须始终是字符串、数字或符号,因此在最坏的情况下,您可以对整个 submission
对象进行字符串化,
:key="JSON.stringify(submission)"
或从一个或多个属性创建字符串。