Vue+Vuex问题:组件内变量离开路由返回后仍保留修改
这事儿的核心在于JavaScript引用类型的特性,以及Vue组件初始化和缓存的机制,我给你拆解清楚:
1. 引用类型赋值导致的“隐形关联”
当你在组件的data()里写:
participants: this.$store.state.participants
你并不是把store里的数组复制了一份,而是让this.participants和store里的participants指向了同一个内存地址的数组对象——因为数组属于引用类型,赋值操作传递的是引用,不是具体的值。
这时候你调用this.participants.push("foo"),本质上就是在修改store里的那个数组本身!虽然你没直接调用Vuex的mutation,但因为引用指向同一个对象,store里的数组已经被悄悄改变了。不过你提到devtools里store是空的,那大概率是你切换路由时,通过mutation把store里的participants重置成了新的空数组(比如state.participants = []),这时候:
- store里是全新的空数组
- 组件data里的
participants还是原来那个被加了"foo"的旧数组
2. 组件缓存让data没重新初始化
如果你的组件被<keep-alive>包裹了,切换路由再返回时,组件不会被销毁重建,而是会被缓存起来。这时候data()函数只会在组件第一次创建时执行一次,后续返回时不会重新运行,所以this.participants还是指向之前那个被修改过的数组,不会去取store里的新空数组。
怎么解决?
如果想让组件数据和store保持同步:别在data里赋值,改用计算属性关联store
computed: { participants() { return this.$store.state.participants } }这样store数组变化时组件会自动更新,而且计算属性是只读的,要修改必须通过Vuex的mutation,能避免误操作。
如果想让组件拥有独立的数组副本:初始化时深拷贝store的数组
data() { return { // 一维数组用扩展运算符浅拷贝就行 participants: [...this.$store.state.participants] // 要是多维数组/对象,就得用深拷贝,比如JSON.parse(JSON.stringify(...)) } }这样组件里的数组和store完全独立,修改不会影响store,而且组件销毁重建时会重新从store取初始值。
如果是keep-alive缓存的问题:在
activated钩子重新同步store值activated() { this.participants = [...this.$store.state.participants] }
内容的提问来源于stack exchange,提问作者AndreasInfo

