1

我尝试了以下。请注意 parent.vue 中的注释行,它甚至没有为我提交新状态。但是,也许有人可以指导我为多个组件共享的全局状态找到更好的解决方案?

main.js

import { createApp } from 'vue'
import App from './App.vue'
import { createStore } from 'vuex'

const app = createApp(App);
export const store = createStore({
    state: {
        textProp: 'test',
        count: 1
    },
    mutations: {
        setState(state, newState) {
            console.log('setState');
            state = newState;
        }
    },
    getters: {
        getAll: (state) => () => {
            return state;
        }
    }

});
app.use(store);
app.mount('#app')

父.vue

<template>
  <div class="parent">
    <div class="seperator" v-bind:key="item" v-for="item in items">
      <child></child>
    </div>
    <button @click="toonAlert()">{{ btnText }}</button>
    <button @click="veranderChild()">Verander child</button>
  </div>
</template>


<script>
import child from "./child.vue";
import {store} from '../main';

export default {
  name: "parent",
  components: {
    child,
  },
  store,
  data: function () {
    return {
      items: [
        {
          id: 1,
          valueText: "",
          valueNumber: 0,
        },
        {
          id: 2,
          valueText: "",
          valueNumber: 0,
        },
        {
          id: 3,
          valueText: "",
          valueNumber: 0,
        },
      ],
    };
  },
  props: {
    btnText: String,
  },
  methods: {
    toonAlert() {
      alert(JSON.stringify(this.$store.getters.getAll()));
    },
     veranderChild() {
       console.log('child aan het veranderen (parentEvent)');
       this.$store.commit('setState', { // This is especially not working.
             textProp: 'gezet via de parent',
             count: 99
         })
       this.$store.commit({type: 'setState'}, {
         'textProp': 'gezet via de parent',
          'count': 99
          });
    },
  },
};
</script>

<style>
.seperator {
  margin-bottom: 20px;
}

.parent {
  /* background: lightblue; */
}
</style>

孩子.vue

<template>
  <div class="child">
    <div class="inputDiv">
      text
      <input @change="update" v-model="deText" type="text" name="deText" />
    </div>
    <div class="inputDiv">
      nummer
      <input v-model="hetNummer" type="number" name="hetNummer" />
    </div>
    <button @click="toonState">Toon huidige state</button>
  </div>
</template>

<script>

import {store} from '../main';

export default {
  name: "child",
  store,
  data: function() {
    return {
      'hetNummer': 0
    }
  },
  methods: {
    update(e) {
      let newState = this.$store.state;
      newState.textProp = e.target.value;
      // this.$store.commit('setState', newState);
    },
    toonState()
    {
      console.log( this.$store.getters.getAll());
    }
  },
  computed: {
    deText: function() {
      return '';
      // return this.$store.getters.getAll().textProp;
    }
  }
};
</script>

<style>
.inputDiv {
  float: right;
  margin-bottom: 10px;
}
.child {
  max-width: 300px;
  height: 30px;
  margin-bottom: 20px;
  /* background: yellow; */
  margin: 10px;
}
</style>
4

2 回答 2

4

你对与 Vue/Vuex 无关的 JavaScript 有一个误解。这不符合您的期望:

state = newState;

解决方案 (TL;DR)

setState(state, newState) {
  Object.assign(state, newState);
}

不要设置state变量,而是合并新属性。

解释

  • JavaScript 中的对象变量是引用。这就是为什么如果您有多个变量引用同一个对象,并且您更改一个属性,它们都会发生变异。它们都只是指内存中的同一个对象,它们不是克隆。

上面的state变量作为对 Vuex 的 state 对象的引用,你知道的。因此,当你改变它的属性时,你也改变了 Vuex 的状态属性。这都很好。

但是,当您将整个变量(不仅仅是一个属性)更改为其他内容时,它不会改变原始引用的对象(即 Vuex 的状态)。它只是破坏了引用链接并为对象创建了一个新链接newState。所以 Vuex 状态根本不会改变。这是一个更简单的演示

观点

state避免这种模式,而是创建一个对象属性。然后你就可以做state.obj = newState

于 2020-11-12T09:44:04.283 回答
0

您应该使用扩展运算符...来改变您的状态,如下所示:

 state = { ...state, ...newState };

活生生的例子

但我建议让您的商店以语义方式更有条理,您的状态中的每个属性都应该有自己的setterand action,getter 相当于选项 API 中的计算属性,它们可以基于多个状态属性。

export const store = createStore({
  state: {
   
    count: 1
  },
  mutations: {
    SET_COUNT(state, _count) {
      console.log("setState");
      state.count=_count
    },
   INC_COUNT(state) {
     
      state.count++
    }
  },
  getters: {
    doubleCount: (state) => () => {
      return state.count*2;
    }
  }
});

**注意:** 不需要从main.js每个孩子中导入商店,因为它可以this.$store在选项 api 中使用,但如果您正在使用组合 api,您可以使用useStore如下:

import {useStore} from 'vuex'
setup(){
    const store=useStore()// store instead of `$store`
}
于 2020-11-12T10:34:59.607 回答