最近在学习vuex时,照着官网最基本的 Vuex 记数应用示例敲的时候遇到了这样一个问题
想实现的效果:
点击加号、减号实现数字增减
vuex设置:
Vue.use(Vuex);
//这里直接把vuex写入vue的原型链,实际上还有更加规范的写法,这里只是方便演示
Vue.prototype.$store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment: state => state.count++,
decrement: state => state.count--
}
});
vue组件:
<template>
<div>
<div>
{{count}}
</div>
<div>
<button v-on:click="add()">+</button>
<button v-on:click="reduce()">-</button>
</div>
</div>
</template>
<script type="text/javascript">
export default {
data(){
return {
count: this.$store.state.count
}
},
methods: {
add(){
this.$store.commit('increment');
console.log(this.count);
},
reduce(){
this.$store.commit('decrement');
console.log(this.count);
}
}
}
</script>
发现点击按钮页面上的数字并没有发生变化,最后参考官网示例发现应该这样在vue组件中获取vuex的state
<script type="text/javascript">
//其余部分和上一段代码一样
export default {
computed: {
count () {
return this.$store.state.count
}
},
methods: {
add(){
this.$store.commit('increment');
console.log(this.count);
},
reduce(){
this.$store.commit('decrement');
console.log(this.count);
}
}
}
</script>
那为什么要使用computed而不是data获取vuex中的state呢?
这是因为data 中的内容只会在 created 钩子触发前初始化一次,具体来说就是data中设置count: this.$store.state.count
则count的值是created钩子执行前this.$store.state.count
的值,赋值之后属性的值就是纯粹的字面量,之后this.$store.state.count
如何变化均影响不到count的取值。就如同下面这段代码
var b = 1;
var a = b;
b = 2;
执行之后a的值依然是1,如此一来我们通过this.$store.commit()
方法来改变state状态就不会改变count的取值。而且一般我们使用data时也是直接将data赋予一个新值,vue的双向绑定机制会更新视图。
而 computed 则是通过【依赖追踪】实现的,计算属性在它的相关依赖发生改变时会重新求值(可参考vue官方教程对计算属性的描述),所以你可以使用 computed 去引用 Vuex 状态变量,从而使得依赖追踪生效