Nuxt 3 - 在父组件中修改时,道具无法响应或正确更新

问题描述 投票:0回答:1

我正在开发 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>

问题:

  • 提交中的任务数组在 createSubmission 方法中异步更新,但更改不会自动传播到子组件(GraderSubmissionInfo 和 GraderSubmissionTask)。
  • 我尝试使用submissions.value[0].tasks = [...tasks];触发反应性更新,但它似乎不会反映在 DOM 中,除非我触发外部更新。 我怀疑问题可能在于 Vue 在这种情况下如何处理反应性,可能与我如何改变任务数组或组件传递数据的方式有关。

任何帮助或见解将不胜感激

javascript vuejs3 nuxt.js nuxt3.js
1个回答
0
投票
对于 v-for 来说,索引不是一个好的

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)"
 或从一个或多个属性创建字符串。

© www.soinside.com 2019 - 2024. All rights reserved.