我同时使用vuex和vuejs 2。

我是vuex的新手,我想看一个商店变量的变化。

我想在我的vue组件中添加手表功能

这是我目前所拥有的:

import Vue from 'vue';
import {
  MY_STATE,
} from './../../mutation-types';

export default {
  [MY_STATE](state, token) {
    state.my_state = token;
  },
};

我想知道my_state是否有任何变化

我怎么看店。My_state在我的vuejs组件?


当前回答

我想尽了一切办法让它运转起来。

理论

我发现,出于某种原因,对$store对象的更改不一定会触发.watch方法。我的解决办法是

Store Create a complex data set which should but doesn't propagate changes to a Component Create an incrementing counter in the state to act as a flag, which does propagate changes to a Component when watched Create a method in $store.mutators to alter the complex dataset and increment the counter flag Component Watch for changes in the $store.state flag. When change is detected, update locally relevant reactive changes from the $store.state complex data set Make changes to the $store.state's dataset using our $store.mutators method

实现

它的实现是这样的:

商店

let store = Vuex.Store({
  state: {
    counter: 0,
    data: { someKey: 0 }
  },
  mutations: {
    updateSomeKey(state, value) {
      update the state.data.someKey = value;
      state.counter++;
    }
  }
});

组件

  data: {
    dataFromStoreDataSomeKey: null,
    someLocalValue: 1
  },
  watch: {
    '$store.state.counter': {
        immediate: true,
        handler() {
           // update locally relevant data
           this.someLocalValue = this.$store.state.data.someKey;
        }
     }
  },
  methods: {
    updateSomeKeyInStore() { 
       this.$store.commit('updateSomeKey', someLocalValue);
  }

可运行演示

这很复杂,但基本上我们在这里观察一个要更改的标志,然后更新本地数据以反映存储在$状态中的对象的重要更改

Vue.config.devtools = false const store = new Vuex.Store({ state: { voteCounter: 0, // changes to objectData trigger a watch when keys are added, // but not when values are modified? votes: { 'people': 0, 'companies': 0, 'total': 0, }, }, mutations: { vote(state, position) { state.votes[position]++; state.voteCounter++; } }, }); app = new Vue({ el: '#app', store: store, data: { votesForPeople: null, votesForCompanies: null, pendingVote: null, }, computed: { totalVotes() { return this.votesForPeople + this.votesForCompanies }, peoplePercent() { if (this.totalVotes > 0) { return 100 * this.votesForPeople / this.totalVotes } else { return 0 } }, companiesPercent() { if (this.totalVotes > 0) { return 100 * this.votesForCompanies / this.totalVotes } else { return 0 } }, }, watch: { '$store.state.voteCounter': { immediate: true, handler() { // clone relevant data locally this.votesForPeople = this.$store.state.votes.people this.votesForCompanies = this.$store.state.votes.companies } } }, methods: { vote(event) { if (this.pendingVote) { this.$store.commit('vote', this.pendingVote) } } } }) <script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script> <script src="https://unpkg.com/vuex@3.5.1/dist/vuex.js"></script> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css"> <div id="app"> <form @submit.prevent="vote($event)"> <div class="form-check"> <input class="form-check-input" type="radio" name="vote" id="voteCorps" value="companies" v-model="pendingVote" > <label class="form-check-label" for="voteCorps"> Equal rights for companies </label> </div> <div class="form-check"> <input class="form-check-input" type="radio" name="vote" id="votePeople" value="people" v-model="pendingVote" > <label class="form-check-label" for="votePeople"> Equal rights for people </label> </div> <button class="btn btn-primary" :disabled="pendingVote==null" >Vote</button> </form> <div class="progress mt-2" v-if="totalVotes > 0" > <div class="progress-bar" role="progressbar" aria-valuemin="0" :style="'width: ' + peoplePercent + '%'" :aria-aluenow="votesForPeople" :aria-valuemax="totalVotes" >People</div> <div class="progress-bar bg-success" role="progressbar" aria-valuemin="0" :style="'width: ' + companiesPercent + '%'" :aria-valuenow="votesForCompanies" :aria-valuemax="totalVotes" >Companies</div> </div> </div>

其他回答

在computed中使用你的getter,然后观察它并做你需要做的事情

    computed:{
    ...mapGetters(["yourGetterName"])
 },
 watch: {
    yourGetterName(value) {
       // Do something you need
    },

  }

通过观察和设置值变化来创建存储变量的Local状态。 这样,表单输入v-model的局部变量更改不会直接改变存储变量。

data() {
  return {
    localState: null
  };
 },
 computed: {
  ...mapGetters({
    computedGlobalStateVariable: 'state/globalStateVariable'
  })
 },
 watch: {
  computedGlobalStateVariable: 'setLocalState'
 },
 methods: {
  setLocalState(value) {
   this.localState = Object.assign({}, value);
  }
 }

如果你使用typescript,那么你可以:

import {Watch} from "vue-property-decorator"; .. @Watch (" $ store.state.something”) private watchSomething() { //使用这个。$store.state。可以访问的东西 ... }

你也可以订阅商店突变:

store.subscribe((mutation, state) => {
  console.log(mutation.type)
  console.log(mutation.payload)
})

https://vuex.vuejs.org/api/#subscribe

比如说,你有一篮水果, 每次你从篮子里添加或取出一个水果,你 想要(1)显示有关水果数量的信息,但你也(2)想要以某种奇特的方式通知水果的数量…

fruit-count-component.vue

<template>
  <!-- We meet our first objective (1) by simply -->
  <!-- binding to the count property. -->
  <p>Fruits: {{ count }}</p>
</template>

<script>
import basket from '../resources/fruit-basket'

export default () {
  computed: {
    count () {
      return basket.state.fruits.length
      // Or return basket.getters.fruitsCount
      // (depends on your design decisions).
    }
  },
  watch: {
    count (newCount, oldCount) {
      // Our fancy notification (2).
      console.log(`We have ${newCount} fruits now, yay!`)
    }
  }
}
</script>

请注意,监视对象中的函数名必须与计算对象中的函数名匹配。在上面的例子中,名字是count。

被监视属性的新值和旧值将作为参数传递到监视回调(count函数)。

篮子商店可以是这样的:

fruit-basket.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const basket = new Vuex.Store({
  state: {
    fruits: []
  },
  getters: {
    fruitsCount (state) {
      return state.fruits.length
    }
  }
  // Obviously you would need some mutations and actions,
  // but to make example cleaner I'll skip this part.
})

export default basket

你可以在以下资源中阅读更多:

计算属性和监视器 API文档:计算 API文档:观察