You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nuxt3/Vue父组件修改Props后子组件未响应更新问题求助

问题分析与解决方案

核心问题原因

  1. 深层响应式未被追踪:直接创建的submission是普通JS对象,虽然submissions是ref数组,但内部的tasks数组及task对象没有被Vue响应式系统深度监听。修改tasks元素属性或替换tasks数组时,Vue无法感知变化。
  2. v-for的key复用问题:使用index作为v-for的key,当数组内容更新时,Vue会复用现有组件实例,不会触发重新渲染,导致DOM不更新。
  3. 子组件状态未联动props:GraderSubmissionTask中的activeComponentKey是固定值,没有根据传入的task.status动态更新,即使task数据变化,图标组件也不会切换。

分步解决方案

1. 修复响应式追踪

在更新tasks时,通过替换整个submission对象触发响应式更新,修改createSubmission中的循环部分:

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';

  // 替换整个submission对象,触发Vue响应式
  submissions.value[0] = {
    ...submissions.value[0],
    tasks: [...tasks]
  };
}

或者初始创建submission时用reactive包裹,确保深层属性可追踪:

import { ref, reactive } from 'vue';

// 创建submission时用reactive
let submission = reactive({
  title: 'Attempt',
  scoreEarned: 0,
  scoreTotal: 20,
  submissionTime: new Date().toUTCString(),
  duration: 503,
  status: 'undf',
  tasks: tasks.map(task => reactive(task)), // 每个task也转为响应式对象
});

submissions.value.unshift(submission);

2. 替换v-for的key为唯一标识

避免使用index作为key,给每个task和submission添加唯一ID,确保Vue能正确识别元素变化:

步骤1:创建带唯一ID的tasks和submission

// 创建tasks时添加唯一id
let tasks = Array.from({ length: taskCount }, (_, index) => ({
  id: `task-${Date.now()}-${index}`,
  status: 'undf',
  title: `Task ${index + 1}`,
  scoreEarned: 0,
  scoreTotal: 20,
  notes: `Notes for Task ${index + 1}`,
}));

// 创建submission时添加唯一id
let submission = {
  id: `submission-${Date.now()}`,
  title: 'Attempt',
  scoreEarned: 0,
  scoreTotal: 20,
  submissionTime: new Date().toUTCString(),
  duration: 503,
  status: 'undf',
  tasks,
};

步骤2:修改模板中的key

Submission Wrapper模板:

<GraderSubmissionInfo 
  v-for="submission in submissions"
  :key="submission.id"
  :submission="submission"
/>

Submission Info模板:

<GraderSubmissionTask 
  v-for="task in submission.tasks"
  :key="task.id"
  :task="task"
/>

3. 子组件联动props更新状态

修改GraderSubmissionTask,监听task.status的变化,动态更新图标组件:

<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, ref, watch, computed, defineAsyncComponent } from 'vue'

const props = defineProps({
  task: Object
})

// 映射status到组件名称
const statusToComponent = {
  undf: 'Progress',
  fail: 'Failed',
  pass: 'Success'
}

// 初始化组件key
let activeComponentKey = ref(statusToComponent[props.task.status] || statusToComponent.undf)

// 监听task.status变化,更新组件key
watch(() => props.task.status, (newStatus) => {
  activeComponentKey.value = statusToComponent[newStatus] || statusToComponent.undf
})

const activeComponent = computed(() => {
  return defineAsyncComponent(() => import(`~/components/Icons/Small/${activeComponentKey.value}.vue`))
})
</script>

验证效果

完成以上修改后,当createSubmission中的异步循环更新tasks时,子组件会自动响应数据变化,DOM会实时更新,无需外部触发。

内容的提问来源于stack exchange,提问作者Jtrom2021

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 13:02:03