为什么需要Vuex
对于多个组件之间使用着相同的data数据,如果某个数据发生了改变。
1. 不能很好的调试知道数据发生变化的过程。
2. 操作麻烦,需要多个组件都进行相对应的操作。
3. 由于在Vue中各个组件之间的作用域是独立的,就比如父组件与子组件间通讯需要props/events,子组件与子组件间通讯还需要定义一个空的vue实例,进行数据传递。
在大型单页面SPA,提供了vuex插件,能让我们的数据存储在某一个特定的位置,然后各个组件间可以共享该数据,而不用考虑组件之间复杂的通讯。
state
状态:可以理解为数据库存储数据的地方
getters
对于state内部的数据二次处理(例如对数据进行过滤 类似filters的作用、例如state返回的一个对象 我们想对该对象中一个键的值用这个方法)
mutations
对state数据进行计算方法全部写在里面(类似于computed计算属性),我们不能直接在组件内部通过(this.)$store.state.stateName改变数据。
唯一的方法是在页面中(this.)$store.commit(‘mutationName’)触发方法改变state的值。
目前我所了解的 mutations与getters不同的是:
getters 获取数据 进行二次处理 并没有改变数据本身
mutations 获取数据 可能改变数据本身
注:mutations属性方法名称尽量用常量
actions
- 在mutations内部只能进行同步操作,而在actions内部可以实现异步操作(setTimeout、setInterval、ES6中Promise等)
- 在actions内部可以通过(this.)$store.dispatch(‘actionName’)实现触发多个mutations方法。
注:actions属性方法名称尽量用常量
modules
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
如果state属性数据过多,不想将数据全部放在一个属性下。可以创建多个module,分别用来存放对应的数据。
注:此时组件中获取数据的方法是(this).$store.state.moduleName.stateName
注:此时组件中使用mutation、getter还是全局下获取(this.)$store.getter.stateName / (this.)$store.commit('mutationName')
安装
npm install Vuex from ‘vuex’
入门
安装vuex之后,如果要使用,必须要引入
//main.js
import Vue from 'vue';
import Vuex from `vuex`;
Vue.use(Vuex);
//main.js
var store = new Vuex.Store({
state: {
count: 0,
number: 10
},
getters: {
GET_COUNT: state=>state.count,
GET_NUMBER: state=>state.number
},
mutations: {
INC_COUNT: state=>state.count++,
INC_NUMBER: state=>state.number++
//你还可以在这里执行其它操作同时改变多个数据
//只能执行同步操作
},
actions: {
ACTIONS_FN: ({commit}) => {
commit('INC_COUNT');
commit('INC_NUMBER');
//你还可以在这里触发多个mutation
//还可以执行异步操作
}
}
});
可以直接在vue实例内部注入store对象。
相对应的根组件会将状态信息自上而下注入到各个子组件内部。
//main.js
new Vue({
el: '#app',
store,
template: '<app></app>', //将index.html中id='app'的标签替换为模板<app></app>
components: {App} //模板<app></app>对应信息为传入过来的App.vue文件
});
//App.vue
<template>
<div class="demo">
<div>App data : {{demo}}</div>
<div>$store.state.count : {{$store.state.count}}</div>
<div>$store.state.number : {{$store.state.number}}</div>
<div>$store.getters.count : {{$store.getters.GET_COUNT}}</div>
<div>$store.getters.number : {{$store.getters.GET_NUMBER}}</div>
<div @click="$store.commit('INC_COUNT')">$store.commit('INC_COUNT')</div>
<div @click="$store.commit('INC_NUMBER')">$store.commit('INC_NUMBER')</div>
<div @click="$store.dispatch('ACTIONS_FN')">$store.dispatch('ACTIONS_FN')</div>
</div>
</template>
<script>
export default{
name: "App",
data () {
return {
demo: "I am App"
}
}
}
</script>
<style></style>
如果觉得每次调用都要一长串字符串表达式,甚至是在多个modules情况下。
可以通过mapState、mapMutations、mapActions辅助函数进行相关的操作,也就是说可以将{{$store.state.count}}重命名为count。
<div>matState count : {{this.count}}</div>
<div @click="INC_COUNT">mapMutations : INC_COUNT</div>
<script>
export default{
name: "App",
//方法一
computed: {
count () {
return this.$store.state.count;
},
number () {
return this.$store.state.number;
}
},
//方法二
computed: mapState([
"count", //等价于 "count": state=>state.count
"number" //注:只是重命名简化,直接修改state数据还是要通过mutations,一般使用最好this.count这么使用..
])
}
<script>
在比如
//方法一
methods: {
INC_COUNT () {
this.$store.commit("INC_COUNT");
}
}
//方法二
methods: mapMutations([
'INC_COUNT',
'INC_NUMBER'
])
注:mapState在computed计算属性内部
注:mapMutations、mapActions在methods属性内部
刚入门vue,后续遇到什么,再做补充。
还有很多不足之处,如果有错解希望能留下自己的见解~
相关学习文章
1. vuex最简单、最详细的入门文档
2. Vuex文档
3. vue全家桶之vuex