Vuex
Vuex是一个专门为Vue.js应用程序开发的状态管理模式。
- 它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
- Vuex也集成到Vue的官方调试工具devtools extension,提供了诸如零配置的time-travel调试、状态快照导入导出等高级调试功能。
使用
安装Vuex:
npm install --save vuex
在src下新建store文件夹,在其中新建index.js作为Vuex的配置文件:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)const store = new Vuex.Store({})
export default store
在main.js中引入注册:
import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store';Vue.config.productionTip = false
new Vue({el: '#app',router,store,components: { App },template: ''
})
仓库store包含了应用的数据(状态)和操作过程。Vuex里的数据都是响应式的,任何组件使用同一个store的数据时,只要store的数据变化,对应的组件也会立即更新。
数据保存在Vuex选项的state 字段内,比如要实现一个计数器,定义一个数据count,初始值为0:
const store = new Vuex.Store({state: {counter: 1000}
})
在App.vue中使用:
<template><div id&#61;"app"><h2>App</h2><h2>{{$store.state.counter}}</h2></div>
</template>
现在访问首页&#xff0c;计数0已经可以显示出来了。
在组件内&#xff0c;来自store的数据只能读取&#xff0c;不能手动改变&#xff0c;改变store中数据的唯一途径就是显示的提交mutations&#xff0c;用来加1和减1。
const store &#61; new Vuex.Store({state: {counter: 1000},mutations: {increment(state) {state.counter&#43;&#43;},decrement(state) {state.counter--}}
})
在组件内&#xff0c;通过this.$store.commit方法来执行mutations。在App.vue中添加两个按钮用于加和键&#xff1a;
<template><div id&#61;"app"><h2>App</h2><h2>{{$store.state.counter}}</h2><button &#64;click&#61;"handleIncrement">&#43;1</button><button &#64;click&#61;"handleDecrease">-1</button></div>
</template><script>import HelloVuex from &#39;./components/HelloVuex&#39;export default {name: &#39;App&#39;,components: {},data() {},methods: {handleIncrement(){this.$store.commit(&#39;increment&#39;)},handleDecrease(){this.$store.commit(&#39;decrement&#39;)}}}
</script><style></style>
mutations还可以接收第二个参数&#xff0c;可以是数字、字符串或对象等类型。比如每次增加的不是1&#xff0c;而是指定的数量&#xff0c;可以这样改写&#xff1a;
mutations: {increment(state, n) {state.counter &#43;&#61; n},decrement(state, n) {state.counter &#43;&#61; n}}
methods: {handleIncrement(){this.$store.commit(&#39;increment&#39;, 10)},handleDecrease(){this.$store.commit(&#39;decrement&#39;, 10)}}
提交mutation的另一种方式是直接使用包含type属性的对象&#xff0c;例如&#xff1a;
increment(state, n) {state.counter &#43;&#61; n.count}
handleIncrement(){this.$store.commit({type: &#39;increment&#39;,count: 10})}
Vuex还有其它三个选项可以使用&#xff1a;getters、actions、modules
getter&#xff1a;&#xff08;类似组件的计算属性computed&#xff09;
假如Vuex定义了某个数据List&#xff0c;它是一个数组&#xff1a;
state: {counter: 1000,list: [1, 5, 8, 10, 30, 50]}
如果只想要得到小于10的的数据&#xff0c;可以在getters中定义过滤方法&#xff1a;
getters: {filteredList: state &#61;> {return state.list.filter(item &#61;> item < 10)}}
在App.vue中使用&#xff1a;
<h2>{{$store.getters.filteredList}}</h2>
getters也可以依赖其它的getter&#xff0c;把getter作为第二个参数&#xff0c;例如再写一个getter&#xff0c;计算出list过滤后的结果的数量&#xff1a;
filteredList: state &#61;> {return state.list.filter(item &#61;> item < 10)},listCount: (state, getters) &#61;> {return getters.filteredList.length;}
<h2>{{$store.getters.listCount}}h2>
<h2>{{$store.getters.filteredList}}h2>
actions:
mutation中不应该异步操作数据&#xff0c;所以有了actions选项。
action在组件内通过$store.dispatch触发&#xff0c;例如使用action来减1,使用Promise在1秒后提交mutation&#xff1a;
mutations: {increment(state, n) {state.counter &#43;&#61; n.count},decrement(state, n) {state.counter -&#61; n}},actions: {asyncDecrement(context){return new Promise((resolve, reject) &#61;> {setTimeout(() &#61;> {context.commit(&#39;decrement&#39;, 10)resolve()}, 1000)})}}
App.vue:
<template><div id&#61;"app"><h2>App</h2><h2>{{$store.state.counter}}</h2><button &#64;click&#61;"handleIncrement">&#43;1</button><button &#64;click&#61;"handleActionDecrease">-1</button><h2>{{$store.getters.listCount}}</h2><h2>{{$store.getters.filteredList}}</h2></div>
</template><script>export default {name: &#39;App&#39;,components: {},methods: {handleIncrement(){this.$store.commit({type: &#39;increment&#39;,count: 10})},handleActionDecrease(){this.$store.dispatch(&#39;asyncDecrement&#39;).then(() &#61;> {console.log(this.$store.state.counter);})}}}
</script><style></style>
modules&#xff1a;
它用来将store分割到不同模块。当项目足够大时&#xff0c;store里的state、getters、mutations、actions会非常多&#xff0c;都放在一个index.js中就不是很友好&#xff0c;使用modules可以把他们写到不同的文件中。
每个module拥有自己的state、getters、mutations、actions&#xff0c;而且可以多层嵌套。
例如&#xff1a;
const moduleA &#61; {state: {...},mutations: {...},actions: {...},getters: {...}
}const moduleB &#61; {state: {...},mutations: {...},actions: {...},getters: {...}
}const store &#61; new Vuex.Store({modules: {a: moduleA,b: moduleB}
})store.state.a
store.state.b
另外&#xff0c;module的mutation和getter接受的第一个参数state是当前模块的状态。在actions和getters中&#xff0c;还可以接收一个参数rootState&#xff0c;来访问根节点的状态。比如getters中rootState将作为第三个参数&#xff1a;
const moduleA &#61; {state: {count: 0},getters: {sumCount (state, getters, rootState) {return state.count &#43; rootState.count;}}
}