Данные диаграммы объекта перезаписываются, но затрагивается только первый объект, с которым взаимодействуют

#vue.js #highcharts #vuex

#vue.js #высокие диаграммы #vuex

Вопрос:

Вот это кодовая песочница, доказывающая и демонстрирующая эту проблему: https://codesandbox.io/embed/ql4rm9734w?fontsize=14

Когда пользователь нажимает на кнопку в приложении. Виджет предназначен для отображения данных этого объекта. Объект содержит массив, который используется для создания графика. Кажется, что нажатие кнопки первого объекта отображается и функционирует правильно. То же самое происходит со вторым и третьим. Но при повторном нажатии кнопки «Первые объекты» свойство данных диаграммы объекта перезаписывается данными диаграммы ранее нажатого объекта.

Приложение было встроено Vue.Js , с Highcharts и официальной оболочкой Highcharts Vue, отображающей графики. Данные хранятся в хранилище Vuex.

Страница заполняется кнопкой для каждого объекта. При нажатии кнопки объектов запускается пользовательское событие, содержащее данные объекта. Обработчик события щелчка объекта изменяет хранилище, передавая объект в хранилище для сохранения в качестве активного объекта-маркера. Виджет объекта, который отображает данные пользователю, получает свои данные из активного объекта маркера stores.

этот процесс отлично работает для любого другого объекта, который использует эту систему. Это также влияет только на первый объект, на который нажат, все последующие объекты не затрагиваются и работают правильно.

Я безуспешно пробовал следующее

  • Vue dev tools и debugging показывает симптомы ошибки, но не указывает, где происходит ошибка.
  • Я попытался сделать свойство data псевдоприватным свойством, доступ к которому возможен только с установщиками и получателями. Установщик никогда не вызывается.
  • Добавлено второе свойство в классе, которое действует как неизмененная переменная хранения для исходных данных, заданных во время построения. Это второе свойство также изменяется.
  • При детальном изучении хранилища было похоже, что ошибка не затронула массив объектов в хранилище. Однако при реорганизации для непосредственного использования объекта из хранилища ошибка все еще сохраняется.
  • Я попытался выделить данные в отдельное свойство состояния, которое не связано с объектом каким-либо прямым образом … все та же ошибка.
  • Я также пробовал с каждым небольшим массивом данных (15 элементов), но ошибка сохранялась.
  • Я даже создал проект мини-реплики в надежде, что при наименьшем масштабе ошибка не появится, и, надеюсь, это будет глупая опечатка или что-то в этом роде… но опять же, даже эта мини-версия моего приложения по-прежнему показывает ошибку. Мини-версию можно найти здесь: https://github.com/ChadRoberts21/ChartMapBug
  • Создан более изысканный пример меньшего размера: https://codesandbox.io/embed/ql4rm9734w?fontsize=14

Код доступен из https://codesandbox.io/embed/ql4rm9734w?fontsize=14

Я ожидаю, что правильные данные диаграммы всегда отображаются в виджете объекта, и для объекта вообще не переопределяется его свойство data, если я явно не решу сделать это в мутации Vuex.

Ответ №1:

Проблема возникает из-за того, что Highcharts изменяет данные, что не совсем соответствует концепциям Vue. Как правило, если вы можете избежать мутации данных, вам вообще не следует этого делать. Я только что ответил на этот вопрос непосредственно в highcharts-vue репозитории, поэтому там вы можете найти более конкретное описание причины возникновения проблемы.

По сути (для других пользователей, ищущих ответ на этот вопрос), лучшим выходом из проблемы будет применение оператора распространения при назначении новых данных ряду:

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

С наилучшими пожеланиями!

Ответ №2:

Я думаю, проблема в том, что вы используете computed для выборки данных. когда вы передаете данные в событии click, это фактически обновленный массив foos хранилища (ссылка на state.foos). поэтому, когда вы нажимаете на test2, данные в хранилище массива foos обновляются.

Попробуйте консольно зарегистрировать массив foos в методе store setActiveFoo вы можете увидеть, что массив 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));
    }
  }
  

Комментарии:

1. Это не должно работать, но это работает. Я все еще считаю, что существует гораздо более глубокая проблема. Почему на другие свойства объекта не влияет та же проблема? В моем производственном приложении у меня есть огромный сложный вложенный объект, который работает отлично, за исключением единственного свойства, которое использует highcharts. Спасибо за ваш ответ, я действительно ценю это!

2. другие свойства объекта не влияют на bcz, вы не используете его в диспетчеризации, а также в других методах. вы просто используете foo-массив состояния, поэтому он влияет только на foos-массив. Проблема в том, что если вы измените значение из возвращаемых методов получения и попытаетесь изменить значение, тогда оно также обновит переменную состояния.