对象的图表数据被覆盖,但仅与第一个交互的对象受影响

时间:2019-04-10 13:45:00

标签: vue.js highcharts vuex

这是一个验证并展示此问题的代码沙箱:https://codesandbox.io/embed/ql4rm9734w?fontsize=14

当用户单击应用程序中的按钮时。小部件旨在显示该对象的数据。该对象包含一个用于生成图形的数组。第一个对象的按钮单击似乎可以正常显示并起作用。第二和第三也是。但是,当再次单击第一个对象按钮时,该对象的图表数据属性将被先前单击的对象的图表数据覆盖。

该应用程序已在Vue.Js中构建,由Highcharts和Highcharts官方Vue包装器绘制图表。数据存储在Vuex存储中。

页面上为每个对象填充了一个按钮。单击对象按钮时,将触发一个包含对象数据的自定义事件。对象单击事件处理程序使将对象传递到商店的商店发生突变,以将其另存为活动标记对象。向用户显示数据的对象Widget从存储的活动标记对象获取其数据。

此过程对于使用此系统的所有其他对象均正常运行。它也只会影响单击的第一个对象,所有后续对象均不受影响并且可以正常工作。

我没有运气尝试过以下

  • Vue开发人员工具和调试程序显示错误的症状,但没有指出错误发生的位置。
  • 我尝试将data属性设置为只能通过setter和getter访问的伪私有属性。设置员永远不会被调用。
  • 在类中添加了第二个属性,以用作构造时给定的原始数据的未修改的存储变量。第二个属性也被修改。
  • 在深入检查商店时,看起来商店中的对象数组不受该bug的影响。但是,当重构为直接使用存储中的对象时,该错误仍然存​​在。
  • 我试图将数据分离为单独的状态属性,该状态属性与对象没有任何直接关系……还是同样的错误。
  • 我还尝试了每个小数据数组(15个元素),但该错误仍然存​​在。
  • 我什至建立了一个迷你副本项目,希望在最小规模下不会出现该错误,并希望这是一个愚蠢的错字之类的东西……但是,即使如此,我的应用程序的这个迷你版本仍然显示出错误。迷你版可以在这里找到:https://github.com/ChadRoberts21/ChartMapBug
  • 构建一个更精致的较小示例:https://codesandbox.io/embed/ql4rm9734w?fontsize=14

可从https://codesandbox.io/embed/ql4rm9734w?fontsize=14

获得该代码。

我希望正确的图表数据始终显示在对象窗口小部件中,并且除非我明确选择在Vuex突变中这样做,否则该对象的数据属性根本不会被覆盖。

2 个答案:

答案 0 :(得分:2)

发生该问题是因为事实上Highcharts会突变数据,而这并不完全符合Vue概念。通常,如果您能够避免数据突变,则根本不应该这样做。我刚刚在highcharts-vue存储库中直接回答了这个问题,所以您可以在其中找到有关问题发生原因的更具体描述。

本质上(对于其他正在寻找该问题答案的用户),解决问题的最佳方法是在为序列分配新数据时应用spread operator

FooWidget.vue( chartOptions()计算属性部分)

series: [{
    showInLegend: false,
    type: "column",
    color: this.foo.colour,
    data: [...this.foo.data],
    pointInterval: this.foo.interval,
    pointStart: this.foo.startPoint,
    gapSize: 4,
    tooltip: {
        valueDecimals: 2
    },
    fillColor: {
        linearGradient: {
            x1: 0,
            y1: 0,
            x2: 0,
            y2: 1
        }
     },
     threshold: null
 }]

实时示例:https://codesandbox.io/s/w2wyx88vxl

最诚挚的问候!

答案 1 :(得分:0)

我认为问题是您正在使用计算机来获取数据。当您在click事件中传递数据时,它实际上是商店的foos数组更新(state.foos的引用)。因此,当您单击test2时,foos数组存储中的数据将更新。

尝试在商店setActiveFoo方法中控制台日志foos数组,您会看到foos数组已使用其他值更新。

setActiveFoo(state, payload) {
      console.log("In store foos")
      console.log(state.foos);
      state.activeFoo = payload;
    }

尝试此代码。我认为您需要以计算方式发送foos数组的副本,它将解决此问题。

computed: {
    foos() {
      return JSON.parse(JSON.stringify(this.$store.getters.foos));
    },
    activeFoo() {
      return JSON.parse(JSON.stringify(this.$store.getters.activeFoo));
    }
  }