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

接口响应返回后Vue组件未重渲染 Pinia+el-table数据不更新

问题根因
  • Pinia状态定义错误:在state配置中手动给值包裹ref()属于冗余操作,Pinia会自动将state返回的普通值包装为响应式代理,手动包裹ref后,后续执行state.equipmentList = response.data时会直接把ref对象替换为普通数组,彻底断开响应式连接,组件无法感知值变化。
  • 组件取值丢失响应式:组件中直接写const equipmentList = state.equipmentList是一次性静态赋值,没有保持对Store状态的响应式引用,Store值更新后组件内的变量不会同步变化。
  • 初始化逻辑存在竞态:入口文件在app.mount('#app')之后才调用initDB(),和组件onBeforeMount钩子中发起的列表请求同时操作equipmentList状态,打乱响应式更新触发时机,和观察到的“接口响应快于初始存储逻辑”“多次切换路由后才正常”的现象完全吻合——路由切换触发组件重挂载时,才会重新拿到Store中的最新值完成渲染。
  • 代码逻辑漏洞:模板中给el-table绑定的:key="loaded"对应状态未在Store中定义,永远为undefined,无法起到强制刷新组件的作用;initDB中判断equipment === 'Firma'存在类型错误,equipment是对象,永远不会等于字符串Firma,该分支逻辑永远不会执行。
修复方案

1. 修正Pinia Store定义

移除state中多余的ref包装,补全缺失的loaded状态:

import { defineStore } from 'pinia'

export const useEquipmentStore = defineStore('equipment', {
  state: () => ({
    equipment: {} as Record<string, any>,
    equipmentList: [] as any[],
    loaded: false
  }),
  actions: {
    reset() {
      this.equipment = {}
      this.equipmentList = []
      this.loaded = false
    }
  }
})

2. 修正组件取值方式

使用Pinia提供的storeToRefs解构Store状态,保持响应式引用,接口请求完成后更新loaded状态触发组件重渲染:

<script setup lang="ts">
import { storeToRefs } from 'pinia'
import { useEquipmentStore } from '~/store/equipmentStore'
import useEquipments from '~/composables/equipments'

const equipmentStore = useEquipmentStore()
const { equipmentList, loaded } = storeToRefs(equipmentStore)
const { getEquipmentList } = useEquipments()

onBeforeMount(async () => {
  await getEquipmentList()
  equipmentStore.loaded = true
})
</script>

<template>
  <el-table :key="loaded" :data="equipmentList" style="width: 100%">
    <el-table-column type="expand">
      <template #default="props">
        ID: {{ props.row.id }}
      </template>
    </el-table-column>
    <el-table-column label="ID" prop="id" />
    <el-table-column label="Name" prop="name" />
  </el-table>
</template>

3. 修正组合式函数逻辑

修复initDB中的判断逻辑错误,调整状态更新方式,确保所有操作都基于响应式状态执行:

import { useRouter } from 'vue-router'
import http from '../http-common'
import { useEquipmentStore } from '~/store/equipmentStore'

export default function useEquipments() {
  const state = useEquipmentStore()
  const errors = ref<string[]>([])
  const router = useRouter()

  const getEquipmentList = async() => {
    try {
      const response = await http.get('/equipment/list')
      // 修正Store后直接赋值即可触发响应式更新,也可使用splice原地更新数组
      state.equipmentList = response.data
    }
    catch (error: any) {
      errors.value.push(error.message)
    }
  }

  const initDB = () => {
    try {
      if (state.equipmentList.length === 0) {
        state.equipmentList.push({ id: 1, name: 'Firma' })
      }
      else {
        // 倒序遍历删除,避免索引错乱
        for (let i = state.equipmentList.length - 1; i >= 0; i--) {
          if (state.equipmentList[i].name === 'Firma') {
            state.equipmentList.splice(i, 1)
          }
        }
      }
    }
    catch (error: any) {
      errors.value.push(error.message)
    }
  }

  return { getEquipmentList, initDB, errors }
}

4. 修正入口文件初始化时序

将initDB调用移到app挂载之前,消除和组件请求的竞态问题:

const pinia = createPinia()
app.use(pinia)
// 挂载前完成初始化
const { initDB } = useEquipments()
initDB()

app.component('InputText', InputText)
app.mount('#app')

修复完成后,接口返回数据时会立即触发el-table重渲染,不需要多次切换路由即可正常展示列表数据。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 16:57:23