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

为何未修改Vuex值却出现自动更新?

问题:修改组件专属data变量时,Vuex数据意外被修改

我搞不懂为什么只修改组件自己的data()变量时,Vue devtools显示我的Vuex数据也发生了变化。

我用Vuex存储获取到的chartData,用来填充ChartJS柱状图。这份数据通过chartDividendsProps这个props传递给DividendChart组件,之后我把chartData加载到ChartJS柱状图组件中。现在点击触发timeFrameChange(e)的按钮时,Vuex中的数据莫名其妙被修改了。

当用户点击“year to date”按钮时触发timeFrameChange方法,该方法会调用getDividends和setYearToDate:

timeFrameChange(e) {
  this.isLoading = true;

  setTimeout(() => {
    this.selectedTimeFrame = e.target.innerText;
    this.isThereData ? this.getDividends() : null;
    this.setYearToDate();
    this.isLoading = false;
  }, 1);
}

从props中获取数据并加载到this.chartData的getDividends方法:

getDividends() {
  this.dividendsArray = [];
  this.chartData.datasets = [];

  this.dividendsArray = this.chartDividendsProps // PROPS

  this.chartData.labels = this.dividendsArray[0].datesList;

  // fill stacked chart
  for (let i = 0; i < this.dividendsArray.length; i++) {
    this.chartData.datasets.push({
      label: this.dividendsArray[i].name,
      isin: this.dividendsArray[i].isin,
      backgroundColor: "#007cda",
      borderRadius: 4,
      borderWidth: 0,
      borderSkipped: "bottom",
      borderColor: "transparent",
      borderDash: [10, 5],
      barPercentage: "1",
      hoverBorderColor: "transparent",
      data: this.dividendsArray[i].dividendsList,
    });
  }
}

用于修改图表时间范围的setYearToDate方法:

setYearToDate() {
  // delete all months before this year
  let currentYear = new Date().getFullYear();

  for (let i = 0; i < this.dividendsArray.length; i++) {
    for (let j = 0; j < this.dividendsArray[i].dividend.length; j++) {
      let dividendYear = parseFloat(this.dividendsArray[i].dividend[j].date.split("-")[1]);

      if (dividendYear < currentYear) {
        this.dividendsArray[i].dividend.splice(j, 1);
        this.dividendsArray[i].datesList.splice(j, 1);
        this.dividendsArray[i].dividendsList.splice(j, 1);
        j--;
      }

    }
  }
},

原因分析

核心问题是引用类型的浅拷贝:Vuex中存储的chartData是数组/对象这类引用类型数据,当你执行this.dividendsArray = this.chartDividendsProps时,并没有复制一份全新的数据,只是让dividendsArray指向了Vuex数据所在的内存地址。之后在setYearToDate里用splice修改dividendsArray的内容,本质上是直接修改了内存中的原数据,也就是Vuex里存储的那份数据。

解决方案

  • 方法1:使用JSON序列化实现深拷贝,修改getDividends中的赋值语句:

    this.dividendsArray = JSON.parse(JSON.stringify(this.chartDividendsProps));
    

    这种方式简单易用,但不支持函数、Symbol等特殊数据类型。

  • 方法2:使用递归实现自定义深拷贝函数,或者借助第三方工具(比如Lodash的_.cloneDeep)处理复杂数据结构。

  • 方法3:在getDividends中只提取需要的字段并创建新对象/数组,避免直接引用原数据,比如:

    this.dividendsArray = this.chartDividendsProps.map(item => ({
      ...item,
      dividend: [...item.dividend],
      datesList: [...item.datesList],
      dividendsList: [...item.dividendsList]
    }));
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 19:55:22