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

Vue3中Pinia嵌套数组Ajax请求后v-for不更新的问题

问题:嵌套数组更新后Vue列表不响应

场景还原

我有一个Pinia仓库SheetItemsStore,代码如下:

const sheetItems = ref([])

function getSheetItems() {
    return axios.get(route('sheet-items.index', {'balance': balance.value.id})).then((response) => {
            sheetItems.value = response.data
    })
}

视图组件中,点击按钮会触发更新并重新获取数据:

<script setup>
import {UseBalanceStore} from "@/Stores/UseBalanceStore.js";
import {UseSheetItemsStore} from "@/Stores/UseSheetItemsStore.js";
import PrimaryButton from "@/Components/PrimaryButton.vue";
import {UseCategoriesStore} from "@/Stores/UseCategoriesStore.js";

const balanceStore = UseBalanceStore()
const sheetItemStore = UseSheetItemsStore()
const categoriesStore = UseCategoriesStore()

function updateReferenceDate(value) {
    axios.patch(route('balances.reference-date.update', {balance: balanceStore.balance.id}), {increase: value}).then(function () {
        balanceStore.getBalance()
        balanceStore.getGrandTotal()
        categoriesStore.getCategories()
        sheetItemStore.getSheetItems()
    })
}
</script>

<template>
    <div class="flex mt-2 mb-2">
        <span class="mt-3 mr-2">Peildatum: {{ balanceStore.balance.reference_date }}</span>
        <PrimaryButton class="mr-2" @click="updateReferenceDate(false)">Maand achteruit</PrimaryButton>
        <PrimaryButton class="mr-2" @click="updateReferenceDate(true)">Maand Vooruit</PrimaryButton>
    </div>
</template>

虽然sheetItemStore.getSheetItems()已触发且AJAX请求正常,但嵌套数组category.sheet_items中的属性更新后,以下v-for列表未响应更新:

<div v-for="category in sheetItemsStore.sheetItems" :key="category.id" :tabindex="category.id" class="card sheet-items-container">
      <div class="flex justify-between card-title">
            <span class="font-bold w-full">{{ category.name.toUpperCase() }}</span>
            <delete-button v-if="editMode" @click="deleteCategory(category)"/>
      </div>

      <div class="sheet-items-list">
           <sheet-item v-for="sheetItem in category.sheet_items"
                   :key="sheetItem.id"
                   :edit-mode="editMode"
                   :sheet-item="sheetItem"
           />
      </div>
 </div>

更新发生在category.sheet_items中sheetItem的属性上,Vue监听器可以设置deep: true,Pinia中是否有类似机制?如何让v-for列表正常更新?

解决方案

方案1:强制替换数组引用

Vue响应式系统对数组的完全替换能直接检测到,若当前替换未触发更新,可通过创建新数组打破原引用:

function getSheetItems() {
    return axios.get(route('sheet-items.index', {'balance': balance.value.id})).then((response) => {
            // 展开数组生成新引用
            sheetItems.value = [...response.data]
            // 若嵌套对象也需完全更新,可使用深拷贝
            // sheetItems.value = JSON.parse(JSON.stringify(response.data))
    })
}

方案2:用reactive处理嵌套结构

改用reactive定义数组,能更好地处理嵌套对象的响应式,配合splice方法更新:

import { reactive } from 'vue'

const sheetItems = reactive([])

function getSheetItems() {
    return axios.get(route('sheet-items.index', {'balance': balance.value.id})).then((response) => {
            // 清空原数组后插入新数据
            sheetItems.splice(0, sheetItems.length, ...response.data)
    })
}

方案3:手动触发响应式更新

若上述方法无效,可手动调用triggerRef强制触发视图更新:

import { ref, triggerRef } from 'vue'

const sheetItems = ref([])

function getSheetItems() {
    return axios.get(route('sheet-items.index', {'balance': balance.value.id})).then((response) => {
            sheetItems.value = response.data
            // 手动触发ref的响应式更新
            triggerRef(sheetItems)
    })
}

方案4:确保嵌套对象为响应式

如果API返回的是普通对象,嵌套层级不会自动转为响应式,可在赋值时手动处理:

import { reactive } from 'vue'

function getSheetItems() {
    return axios.get(route('sheet-items.index', {'balance': balance.value.id})).then((response) => {
            sheetItems.value = response.data.map(category => ({
                ...category,
                // 将每个sheet_item转为响应式对象
                sheet_items: category.sheet_items.map(item => reactive(item))
            }))
    })
}

总结

最稳定的方式是每次更新时创建新数组引用,让Vue自动检测变化;若涉及嵌套属性修改,需确保嵌套对象本身是响应式的,或通过手动触发更新强制刷新视图。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 05:40:20