【问题标题】:Error:[vuex] do not mutate vuex store state outside mutation handlers vuex (nuxt.js)错误:[vuex] 不要在突变处理程序 vuex (nuxt.js) 之外改变 vuex 存储状态
【发布时间】:2021-02-18 14:44:27
【问题描述】:

我已经搜索了导致此错误消息出现的原因,但在我的代码中无法真正理解它。我将 Nuxt.js 与 Vuex 一起使用。我只是看不到我在哪里修改了没有突变的商店。有人可以告诉我我在做什么错吗?当我从日期选择器组件中选择某个日期时,会出现此错误消息。该解决方案按预期工作,只是错误消息让我感到困扰,我真的不想通过关闭 store 的严格模式来解决它。

组件.vue

<template>
  <v-col class="chart">
    <v-card>
      <v-card-title>Daily beta trend</v-card-title>
      <v-row>
        <v-col cols="4">
          <b-form-group label="From" class="ml-3">
            <b-form-datepicker id="datepicker-from" v-model="chartDataFrom" class="mb-2" />
          </b-form-group>
        </v-col>
        <v-col cols="4">
          <b-form-group label="To">
            <b-form-datepicker id="datepicker-to" v-model="chartDataTo" class="mb-2" />
          </b-form-group>
        </v-col>
        <v-col cols="4">
          <b-form-group label="OS Version" class="mr-3">
            <b-form-select v-model="selectedOS" :options="OSVersions">
              <template #first>
                <b-form-select-option :value="null" disabled>
                  -- Please select OS version --
                </b-form-select-option>
              </template>
            </b-form-select>
          </b-form-group>
        </v-col>
      </v-row>
      <v-skeleton-loader
        v-if="$fetchState.pending"
        class="mx-auto"
        max-width="300"
        type="card"
      />
      <p v-else-if="$fetchState.error">
        An error occurred :(
      </p>
      <div v-else>
        <Chart :data="chartData" />
      </div>
    </v-card>
  </v-col>
</template>

<script>
import Chart from '~/components/Trends/Charts/Chart'
export default {
  name: 'BetaTrend',
  components: {
    Chart
  },
  async fetch () {
    await this.$store.dispatch('beta_trend/getChartData')
  },
  fetchOnServer: false,
  computed: {
    chartData: {
      get () {
        return this.$store.state.beta_trend.chartData
      },
      set (data) {
        this.$store.commit('beta_trend/SET_CHART_DATA', data)
      }
    },
    chartDataFrom: {
      get () {
        return this.$store.state.beta_trend.from
      },
      set (value) {
        this.$store.commit('beta_trend/SET_FROM', value)
        this.$fetch()
      }
    },
    chartDataTo: {
      get () {
        return this.$store.state.beta_trend.to
      },
      set (value) {
        this.$store.commit('beta_trend/SET_TO', value)
        this.$fetch()
      }
    },
    OSVersions: {
      get () {
        return this.$store.state.beta_trend.os
      }
    },
    selectedOS: {
      get () {
        return this.$store.state.beta_trend.selectedOs
      },
      set (value) {
        this.$store.commit('beta_trend/SET_SELECTED_OS', value)
        this.$fetch()
      }
    }
  }
}
</script>

<style scoped>

</style>

商店是这样定义的:

export const state = () => ({
  chartData: [],
  from: null,
  to: null,
  os: [
    'All',
    '1803',
    '19042'
  ],
  selectedOs: null
})

export const mutations = {
  SET_CHART_DATA (state, data) {
    state.chartData = data
  },
  SET_FROM (state, from) {
    state.from = from
  },
  SET_TO (state, to) {
    state.to = to
  },
  SET_SELECTED_OS (state, os) {
    state.selectedOs = os
  }
}

export const actions = {
  async getChartData ({ commit, state }) {
    const data = await this.$axios.$get('api/frontend/trend/XXX', {
      params: {
        from: state.from,
        to: state.to,
        os: state.selectedOs
      }
    })
    commit('SET_CHART_DATA', data)
    if (state.from === null) {
      commit('SET_FROM', data.dates[0])
    }
    if (state.to === null) {
      commit('SET_TO', data.dates[data.dates.length - 1])
    }
  }
}

【问题讨论】:

    标签: javascript vuejs2 nuxt.js vuetify.js vuex


    【解决方案1】:

    我通过在我的 computed 选项的 get() 上使用 Lodash 的 cloneDeep 方法来解决此问题。我确实有深度复制的状态,这样它可以防止实际对象的任何突变,因此可以通过 set() 以相同的方式进行修改。

    唯一需要的是

    import { cloneDeep } from 'lodash-es'
    
    export default {
    [...]
    
    chartData: {
      get () {
        return cloneDeep(this.$store.state.beta_trend.chartData)
      },
      [...]
    },
    

    PS:另外值得一提的是JSON.parse(JSON.stringify(object))不推荐:https://flaviocopes.com/how-to-clone-javascript-object/#wrong-solutions

    【讨论】:

    • 谢谢!!我刚刚使用 JSON.parse 方法找到了类似的解决方案,但我在 Chart 组件中将其用作计算属性,该属性会复制传递的道具。工作方式相同,但您的解决方案更优雅。
    猜你喜欢
    • 2020-03-30
    • 2023-03-09
    • 1970-01-01
    • 2019-09-24
    • 2018-02-13
    • 2020-04-08
    • 2022-01-09
    • 2021-11-30
    • 2019-11-30
    相关资源
    最近更新 更多