Vuejs Vuex 状态覆盖外部存储而无需突变或直接访问状态

Vuejs Vuex state overrides outside store without mutation or direct access to state

map() 中的 Vuex 状态覆盖

预期行为 - count点击触发按钮时总是 1

当前行为是 count 每次点击触发按钮时都会增加 如果我们查看控制台日志,我们可以看到 getter returns 突变状态

const store = new Vuex.Store({
    state: {
        stuff: [{
            count: 0
        }]
    },
    mutations: {},
    getters: {
        stuff: s => s.stuff,
    }
})

new Vue({
    el: '#vue',
    store,
    data() {
        return {
            res: []
        }
    },
    methods: {
        trigger() {
            const stuff = this.$store.getters.stuff
            console.log(stuff)
            const res = stuff.map(p => {
                p.count += 1
                return {
                    ...p
                }
            })
            this.res = res
        }
    },
})
 <script src="https://cdn.jsdelivr.net/npm/vue@2.6.12/dist/vue.js"></script>  <script src="https://unpkg.com/vuex@3.6.2/dist/vuex.js"></script>
 <div id="vue">
  <div>
   <button @click=trigger()>Trigger</button>
   <pre>{{res}}</pre>
  </div>
 </div>

这是意料之中的。 Vuex 只是 JS 虚拟机内部的一个库 - JS 的规则适用...

Value vs. Reference

  1. const stuff = this.$store.getters.stuff - stuff 现在是对现有对象(在本例中为数组)的引用
  2. stuff.map() 迭代数组将每个项目作为 p 参数传递。如果 p 是一个对象,p 是对 Vuex 内部对象的引用——如果你修改它,你就是在修改 Vuex store
  3. 内部的对象

这很糟糕,为了确保安全,您可以将 Vuex 设置为在 Vuex 中的任何时候抛出错误 modified without using mutation

const store = new Vuex.Store({
  // ...
  strict: process.env.NODE_ENV !== 'production'
})