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

Vue.js中如何传递修改后的数据?解决provide未感知数组更新问题

问题原因

你遇到的核心问题是:provide 初始传递的是旧数组的引用,当你通过 this.cards = this.cards.concat(gameCards) 替换数组引用时,provide 里的 cards 并没有同步更新到新数组,导致依赖 inject 获取数据的组件拿到的还是初始的4个元素。另外注意你的原代码存在语法错误——methods 被写在了 created 函数内部,这会导致 prepareCards 方法无法正常执行,修正语法是前提。

解决方法

方案一:用响应式包装对象(Vue2/3通用)

把 cards 放在一个响应式的对象里,provide 这个包装对象,这样修改对象的属性时,子组件能感知到变化:

export default {
  components: {
    GameBoard,
  },
  data() {
    return {
      cardStore: {
        cards: [
          {id: "penguin", name: "penguin"},
          {id: "tiger", name: "tiger"},
          {id: "monkey", name: "monkey"},
          {id: "lion", name: "lion"},
        ]
      }
    };
  },
  provide() {
    return {
      cardStore: this.cardStore
    };
  },
  created() {
    this.prepareCards();
  },
  methods: {
    prepareCards() {
      let gameCards = [];
      for (let i = 0; i < this.cardStore.cards.length; i++) {
        gameCards.push({
            id: this.cardStore.cards[i].name + 2,
            name: this.cardStore.cards[i].name + 2,
        });
      }
      this.cardStore.cards = this.cardStore.cards.concat(gameCards);
      console.log("gameCards: " + JSON.stringify(this.cardStore.cards));
    }
  }
}

子组件通过 inject 接收后,使用 cardStore.cards 循环:

<CardResource
  v-for="card in cardStore.cards"
  :key="card.id"
  :id="card.id"
  :name="card.name"
></CardResource>

方案二:Vue2 专用 - 使用 Vue.observable

如果不想改数据结构,用 Vue.observable 创建响应式的提供对象,同步更新引用:

import Vue from 'vue';

export default {
  components: {
    GameBoard,
  },
  data() {
    return {
      cards: [
        {id: "penguin", name: "penguin"},
        {id: "tiger", name: "tiger"},
        {id: "monkey", name: "monkey"},
        {id: "lion", name: "lion"},
      ]
    };
  },
  provide() {
    return Vue.observable({
      cards: this.cards
    });
  },
  created() {
    this.prepareCards();
  },
  methods: {
    prepareCards() {
      let gameCards = [];
      for (let i = 0; i < this.cards.length; i++) {
        gameCards.push({
            id: this.cards[i].name + 2,
            name: this.cards[i].name + 2,
        });
      }
      this.cards = this.cards.concat(gameCards);
      this._provided.cards = this.cards;
      console.log("gameCards: " + JSON.stringify(this.cards));
    }
  }
}

方案三:Vue3 专用 - 使用 ref/reactive

Vue3 中直接用响应式API定义数据,provide 响应式对象即可:

import { ref, provide } from 'vue';

export default {
  components: {
    GameBoard,
  },
  setup() {
    const cards = ref([
      {id: "penguin", name: "penguin"},
      {id: "tiger", name: "tiger"},
      {id: "monkey", name: "monkey"},
      {id: "lion", name: "lion"},
    ]);

    provide('cards', cards);

    const prepareCards = () => {
      let gameCards = [];
      for (let i = 0; i < cards.value.length; i++) {
        gameCards.push({
            id: cards.value[i].name + 2,
            name: cards.value[i].name + 2,
        });
      }
      cards.value = cards.value.concat(gameCards);
      console.log("gameCards: " + JSON.stringify(cards.value));
    };

    prepareCards();

    return { cards };
  }
}

子组件接收方式:

<script setup>
import { inject } from 'vue';
const cards = inject('cards');
</script>

<template>
  <CardResource
    v-for="card in cards"
    :key="card.id"
    :id="card.id"
    :name="card.name"
  ></CardResource>
</template>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 02:45:03