vuex定义:vuex是一个专门为vue.js设计的集中式状态管理架构。
vuex的个人理解:
是存储公有状态数据state的一个仓库(store);解决了大型应用时组件传参的繁杂和不易维护性;vuex的状态储存是响应的,store中状态发生改变后相应组件会得到更新;不能直接修改store中的状态,唯一途径是显示的提交(commit)mutation, 可以通过getter获取state的派生值;
Vuex结构组成:
Store(仓库):
State(状态):负责存储应用的状态数据,可以理解为数据容器;组件中获取vuex中的数据时使用this.$store.state.stateName来获取;
Mutations(变化):利用它来更改状态state数据,本质是处理数据的函数,其接收唯一参数值state。我们可以在methods方法中使用this.$store.commit(‘mutationName’);来触发一个mutation的方法;必须是同步函数,否则devtool中的数据将会出现问题;
Actions:通过触发mutation来修改state状态,重要的是可以异步改变state状态,在methods方法中使用this.$store.dispatch(actionName);直接触发
Getters:有些状态需要进行二次处理就可以使用getters,可以在方法中使用this.$store.getters.valueName对派生出来的状态数据进行访问;当依赖发生改变时会改变
mapActions、mapMutations、mapGetters、mapState:是利用辅助函数将actions、mutations、getters、state映射到本地计算属性或methods方法中去;使用前需引入映射如: import {mapGetters} from ‘vuex’
第一步:创建项目
基于vue-cli脚手架生成一个vue项目;
常用命令:
npm i vue-cli --g 来安装vue-cli
vue --vesion 或 vue -V 来检查vue安装是否成功
vue init webpack 项目名 来创建vue-cli 脚手架项目
注意:当运行 npm i vue-cli --g 安装vue-cli报 “ WARN deprecated [email protected]: CoffeeScript on NPM has moved to "coffeescript" (no hyphen) ” 错误时可以尝试 使用 cnpm i vue-cli --g 安装
第二步:检查项目是否创建成功,安装vuex
npm run dev 来运行vue项目
npm i vuex --save 来安装vuex
第三步:代码实现父子组件通过vuex传递参数Demo
效果:
1、项目文件结构如下: 创建父子组件文件和store.js文件
2、Store.js文件引用vuex如下:
import Vue from 'vue';
import Vuex from 'vuex';
//vue引用vuex
Vue.use(Vuex);
//state状态数据容器
const state={
testMsg:"state中的一行测试文本",
parentMsg:"父组件原始文本",
childMsg:"子组件原始文本",
count:99,
}
//修改satate的方法,就是state状态数据的处理函数
const mutations= {
changeParentMsg:function(state,str){
state.parentMsg=str;
},
changeChildMsg:function(state,str){
state.childMsg=str;
},
}
//异步,通过commit触发mutations中的方法来修改state
const actions={
changeParentTxt({commit},data){
commit('changeParentMsg',data);
},
changeChildTxt:function(context,data){
context.commit('changeChildMsg',data);
},
//上述两个方法中的参数使用{commit}和context均有效,context代表store本身
}
//对获取到的state数据进行过滤修改
const getters={
countNum:function(state){
if(state.count>100){
return state.count+100;
}else {
return state.count-50;
}
}
}
//创建store实例,将在main.js文件中将它加入到vue实例对象中
export default new Vuex.Store({ //export default 是封装代码,使外部可用
state, //依此加入到store对象中
mutations,
actions,
getters,
});
3、Main.js文件在vue实例中引用store对象:
将store实例从根组件中‘注入’到子组件中,子组件通过‘this.$store’调用
4、组件文件:
HelloWorld.vue
测试文本如下:
在组件模板中直接输出获取值:{{$store.state.testMsg}}
getters获取state的值修改后如下:
{{$store.getters.countNum}}
Parent.vue
父组件的内容:
{{oldtxt}}
Child.vue
子组件的内容:
{{oldtxt}}
1、组件模板获取state状态数据:将状态对象赋值给内部对象,也就是将stroe.js中的值赋值给模板中的data中的值,有三种赋值方式:
①使用computed计算属性直接赋值;
②使用mapState辅助函数来赋值(将state值映射到局部计算属性);
③使用mapState的数组来赋值;
computed计算属性获取的值:{{count01}}
使用mapState辅助函数来赋值:{{count02}}
使用mapState的数组来赋值:{{count}}
computed:{ //多个computed时,后面的会覆盖前面的
count01(){ //普通计算属性
return this.$store.state.count;
},
...mapState({ //mapState(obj)对象辅助函数赋值
count02:(state)=>{return state.count} //ES6的箭头函数
}),
...mapState(['count']) //mapState(arr)数组来赋值
}
2、getters获取的是经过加工过滤后的state状态数据。
//store.js中getters定义
//对获取到的state数据进行过滤修改
const getters={
changeCount:function(state){
if(state.count>100){
return state.count*2;
}else {
return state.count-1;
}
}
}
const mutations= {
addCount:function(state,num){
return state.count+=num;
},
}
// 组件模板中使用mapGetters
原值:{{count}}
getter加工过滤后的值:{{changeCount}}
同理在组件模板可以通过this.$store.getters.changeCount来获取store中过滤更改后的count值;
mapGetters辅助函数和mapState辅助函数类似是将store中的getter 映射到局部计算属性computed中,mapGetters使用前先import引入;
3、组件模板更改store中的state值通过mutations中的方法:mutations同步更改状态($store.commit('mutationName'))的方式:
①使用this.$store.commit('mutationName');
//store.js
//mutations中更改satate的方法,就是state状态数据的处理函数
const mutations= {
addCount:function(state,num){
return state.count+=num;
},
reduceCount:function(state,num){
return state.count-=num;
},
}
②使用mapMutations辅助函数将mutations中的方法映射到methods中;
a、组件中首先需要使用import 引入mapMutations和mapState(依赖性),如
import {mapState,mapMutations} from 'vuex'
b、将mutations中的方法映射到methods中;
methods:{
...mapMutations(['reduceCount']),
},
c、组件模板中直接使用映射的方法如:
4、actions异步更改状态state,actions方法通过mutations中方法来更改state,actions中的方法有两种写法如下:
//异步,通过commit触发mutations中的方法来修改state
const actions={
changeParentTxt({commit},data){
commit('changeParentMsg',data);
},
changeChildTxt:function(context,data){
context.commit('changeChildMsg',data);
},
//上述两个方法中的参数使用{commit}和context均有效,context代表store本身
}
mapActions的使用类似mapMutations将方法映射到methods中,组件模板使用前先 import 引用mapActions、mapMutations、mapState;
methods:{
changeCountNum:function(){
this.$store.dispatch("countNum_action",99); //$store.dispatch("actionName");直接触发actions中的方法
},
},
5、module模块组:为解决state状态对象过多而杂的问题,我们将一个store划分为多个module模块,每个模块拥有自己的state、mutations、actions、getters使用如下
①store.js中是声明modules
//声明模块组module
const moduleA={
state:{
name:'zhangsan',
age:27
},
mutations:{},
actions:{},
getters:{}
};
const moduleB={
state:{
name:'wangwu',
age:26
},
mutations:{},
actions:{},
getters:{}
};
export default new Vuex.Store({
modules:{a:moduleA,b:moduleB} //使用a做为moduleA的别名,b同理
});
②模板组件中获取指定module中的state数据有以下两种方式
模块A的name值是:{{$store.state.b.name}}
computed:{
moduleAname:function(){
return this.$store.state.a.name;
}
},
1、如果store文件太大,也可以将 action、mutation 和 getter 分割到单独的文件。分割的文件需要export default 导出,并在store.js文件中的import 导入,如下
//mymutations.js 文件
const mutations= {
changeParentMsg:function(state,str){
state.parentMsg=str;
},
changeChildMsg:function(state,str){
state.childMsg=str;
},
}
export default mutations
import state from './mystate'
import mutations from './mymutation'
import actions from './myactions'
export default new Vuex.Store({
state,
mutations,
actions,
getters,
});
2、在vue 的构造器里边只能有一个computed属性,如果你写多个,只有最后一个computed属性可用;
3、vuex数据在页面刷新时数据会丢失问题,解决思路是vuex更改state数据时同时存储到sessionStorage,当getters获取state数据时判断state为空时对应sessionStorage是否存在,为true则获取sessionStorage赋值给丢失了数据的stateName,如下:
//store.js中定义getters获取时为空会判断从sessionStorage获取值或初始值
const getters={
countNum:function(state){
if(!state.count){
state.count=10; //首次num数值为空初始值赋值为10
let sessionVal=sessionStorage.getItem("count_num");
if(sessionVal){
state.count=parseInt(sessionVal);
}
}
return state.count
}
}
//store.js中定义mutations更改state后存储到sessionStorage
const mutations= {
change_numCount:function(state,data){
state.count=data;
sessionStorage.setItem('count_num',data);
},
}
//组件模板中触发更改state状态数据的action方法
methods:{
changeCountNum:function(){
this.$store.dispatch("countNum_action",99);
},
},
参考网址:https://blog.csdn.net/H5_QueenStyle12/article/details/75386359
https://blog.csdn.net/mjzhang1993/article/details/78321903