今天在做Vue开发的时候遇到了个很奇怪的现象:改变了Vuex中的state
的数据,但是页面没有做出改变。
首先放出代码:
Vuex:
import { createStore} from'vuex'; /** * 用户构造函数 * @param {*} name 用户名 */functionUser(name) { this.name=name; /** * 修改用户名 * @param {String} changedName 修改后用户名 */this.changeName= (changedName) => { this.name=changedName; } } exportdefaultcreateStore({ state: { user: newUser('swsk33') }, mutations: { change(state) { state.user.changeName('swsk'); console.log(state.user.name); } }, actions: { change(context) { context.commit('change'); } }, });
Vue组件:
<template><divid="app"><div></div><div@click="change">更改</div></div></template><script>import { mapState, mapActions } from'vuex'; exportdefault { computed: { mapState(['user']), }, methods: { mapActions(['change']), }, }; </script>
可见,在Vuex中,方便起见我定义了个构造函数,用于创建用户对象。可以看到,用户对象中有一个changeName
函数可以更改自己的用户名,这个函数相当于可以更改自己的值。
然后在state
中初始化一个用户对象,并定义好mutations
,actions
函数以测试更改,注意mutations
中方法是使用用户对象自己的方法修改用户名,而不是直接赋值。
最后,vue组件中,映射Vuex中的user
和change
函数进行测试。理论上,我点击更改时,显示的用户名会变,然而点击后并没有变。
点击后网页:
网页上内容并没有变。
但是在控制台中输出这个state
中的user
,实质上已经改变了:
我们知道,state
中的数据也是响应式的,而更改其数据的唯一方法就是mutations
。
但是可见,上述修改数据的形式并不同于平时,没有在mutations
进行直接赋值,而是使用对象自己的方法修改自己。
这就是问题所在:mutations
中的函数没有进行一个直接的更改对象的操作,而是间接地调用对象自己的方法修改对象自己。
这样,数据确实修改了,但是可以理解为:并非是mutations
进行修改的。
这种情况下,mutations
没有直接修改数据,就导致Vue中无法侦测到数据变化做出响应。
解决办法很简单,不要在构造函数中定义修改对象自己属性的方法,而是使用mutations
修改即可。
我们修改上述Vuex如下:
import { createStore} from'vuex'; /** * 用户构造函数 * @param {*} name 用户名 */functionUser(name) { this.name=name; } exportdefaultcreateStore({ state: { user: newUser('swsk33') }, mutations: { changeName(state) { // 进行直接修改操作state.user.name='swsk'; } }, actions: { change(context) { context.commit('changeName'); } }, });
所以,使用Vuex时,一定要牢记官方文档的这一句话:更改Vuex的store中的状态的唯一方法是提交mutation。
任何修改数据的操作应当放在mutations
中,而非别的函数里面。