【Vue】15 VueX
【什么是VueX?】
VueX是一个专门为Vue.js应用程序开发的状态管理模式,
采用集中式存储管理应用的所有组件状态,
以相应的规则保证按照一种可预测的方式发生改变。
即把多个组件的变量统一放到一个地方管理
在项目中安装Vuex
npm install vuex
新建store目录和一个index.js
并写入以下代码:
import Vue from 'vue'; import VueX from 'vuex'; Vue.use(VueX); const store = new VueX.Store({ state : { count : 0 }, mutations : { increment(state) { state.count++; }, decrement(state) { state.count--; } } }); export default store;
其次,我们要让所有的Vue组件,都能使用store,
就需要在main.js中引入,引入方式与router一样
import Vue from 'vue' import App from './App.vue' import router from "./router"; // ./router/index.js 因为是index.js,可以默认不写 import store from "./store"; Vue.config.productionTip = false new Vue({ render: h => h(App), router, store }).$mount('#app');
在任意一个Vue组件中插值引入:
<template> <div> <h2>样本的标题</h2> <p>样本的标签</p> <p>{{$store.state.count}}</p> </div> </template> <script> export default { name: "sample" } </script> <style scoped> </style>
可以看到这里已经完全取出来了
然后再编写两个按钮和对应的事件:
<template> <div> <h2>样本的标题</h2> <p>样本的标签</p> <p> <button @click="decrease">减少</button> {{$store.state.count}} <button @click="increase">增加</button> </p> </div> </template> <script> export default { name: "sample", methods : { decrease() { this.$store.commit("decrement"); }, increase() { this.$store.commit("increment"); } } } </script> <style scoped> </style>
查看效果:
然后再主页面也渲染这个变量:
可以发现,是一样的:
就是为了一些公共变量而存在的
【State】
Vuex提出使用单一状态树,(单一数据源),就是将一堆公共的数据放到一起去管理
state的意义类似Vue实例的data对象,所有的数据信息存放state中,但是访问不建议也像vue那样直接引用
【Gettter】
我们需要从state中获取一些经过改变后的数据,可以使用getter
store的index.js
import Vue from 'vue'; import VueX from 'vuex'; Vue.use(VueX); const store = new VueX.Store({ state : { count : 0, studentList : [ { id : 1, name : "张三", age : 23, gender : true }, { id : 2, name : "李四", age : 24, gender : true }, { id : 3, name : "王五", age : 25, gender : true }, { id : 4, name : "阿伟", age : 26, gender : true }, { id : 5, name : "杰哥", age : 27, gender : true }, ] }, mutations : { increment(state) { state.count++; }, decrement(state) { state.count--; } }, getters : { getStudentByAge(state) { return state.studentList.filter(e => e.age > 24); } } }); export default store;
在组件中可以通过this.$store.getters.xxx获取
<p> {{$store.getters.getStudentByAge}} </p>
效果:
【Mutations】
用于对state中的数据进行修改,或者是传值,类似vue实例的methods
调用mutations中的方法,需要这样:
this.$store.commit('方法名称',参数列表)
【Actions】
需要注意的是,我们不会在mutations进行异步操作:【使用规范】
但是在某些特定需求的情况下必须使用:比如ajax异步请求
这时候我们就可以使用actions处理:
作用就是为了代替mutations来完成这种功能
context参数,是和Store对象具有相同方法和属性的对象
即我们可以使用context.commit调用mutations
import Vue from 'vue'; import VueX from 'vuex'; Vue.use(VueX); const store = new VueX.Store({ state : { count : 0, studentList : [ { id : 1, name : "张三", age : 23, gender : true }, { id : 2, name : "李四", age : 24, gender : true }, { id : 3, name : "王五", age : 25, gender : true }, { id : 4, name : "阿伟", age : 26, gender : true }, { id : 5, name : "杰哥", age : 27, gender : true }, ] }, mutations : { increment(state) { state.count++; }, decrement(state) { state.count--; } }, getters : { getStudentByAge(state) { return state.studentList.filter(e => e.age > 24); } }, actions : { increa(context) { context.commit('increment'); } } }); export default store;
调用actions的方法需要使用dispatch分发
<template> <div> <h2>样本的标题</h2> <p>样本的标签</p> <p> <button @click="decrease">减少</button> {{$store.state.count}} <button @click="increase">增加</button></p> </div> </template> <script> export default { name: "sample", methods : { decrease() { this.$store.commit("decrement"); }, increase() { // this.$store.commit("increment"); this.$store.dispatch('increa'); } } } </script> <style scoped> </style>
其实对比发现,就是多一个action处理:
actions可用于异步操作,即可以使用Promise,
在异步操作中放入Promise,成功或者失败后,调用对应函数
import Vue from 'vue'; import VueX from 'vuex'; Vue.use(VueX); const store = new VueX.Store({ state : { count : 0, studentList : [ { id : 1, name : "张三", age : 23, gender : true }, { id : 2, name : "李四", age : 24, gender : true }, { id : 3, name : "王五", age : 25, gender : true }, { id : 4, name : "阿伟", age : 26, gender : true }, { id : 5, name : "杰哥", age : 27, gender : true }, ] }, mutations : { increment(state) { state.count++; }, decrement(state) { state.count--; } }, getters : { getStudentByAge(state) { return state.studentList.filter(e => e.age > 24); } }, actions : { increa(context) { context.commit('increment'); }, mp(context) { return new Promise(resolve => { setTimeout(() => { context.commit("decrement"); resolve(); }, 1000); }); } } }); export default store;
组件这里:
<template> <div> <h2>样本的标题</h2> <p>样本的标签</p> <p> <button @click="decrease">减少</button> {{$store.state.count}} <button @click="increase">增加</button></p> </div> </template> <script> export default { name: "sample", methods : { decrease() { // this.$store.commit("decrement"); this.$store.dispatch('mp').then(res => { alert("数据跟新完毕"); }); }, increase() { // this.$store.commit("increment"); this.$store.dispatch('increa'); } } } </script> <style scoped> </style>
每次点击减少按钮就会晚一秒执行,然后再弹窗警告:
【Modules】
模块,vuex使用了单一状态树,当我们的状态过多时,使用store管理可能臃肿,这时候可以按照模块区划分vuex的store数据
当然,store还是可以统一管理module的
每个module即一个小的vuex,都具备上面的那些属性【getters,state,actions . . .】
import Vue from 'vue'; import VueX from 'vuex'; Vue.use(VueX); const user = { state : { studentList : [ { id : 1, name : "张三", age : 23, gender : true }, { id : 2, name : "李四", age : 24, gender : true }, { id : 3, name : "王五", age : 25, gender : true }, { id : 4, name : "阿伟", age : 26, gender : true }, { id : 5, name : "杰哥", age : 27, gender : true }, ], token : "", name : '', header : '', }, getters : { getStudentByAge(state) { return state.studentList.filter(e => e.age > 24); } } } const baseData = { state : { count : 0, }, mutations : { increment(state) { state.count++; }, decrement(state) { state.count--; } }, actions : { increa(context) { context.commit('increment'); }, mp(context) { return new Promise(resolve => { setTimeout(() => { context.commit("decrement"); resolve(); }, 1000); }); } } } const store = new VueX.Store({ modules : { user, baseData } }); export default store;
组件中的调用也需要更改:
<p> {{$store.state.baseData.count}} </p> <p> {{$store.getters.getStudentByAge}} </p>
如果再index.js有太多的模块,可以抽取成文件,引入使用: