初学Vue(全家桶)-第16天(vuex):vuex简介
初学Vue
文章目录
- 初学Vue
- 1、vuex是什么
- 定义
- vuex工作原理
- 2、配置vuex环境和使用
- 使用案例
- 3、getter配置项
- 5、四个map方法的使用
- 6、vuex模块化+命名空间
1、vuex是什么
定义
专门在Vue中实现集中式状态(数据)管理的一个插件,对Vue应用中多个组件的共享状态进行集中式管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信。
- 什么时候用vuex?
1、多个组件依赖于同一状态
2、来自不同组件的行为需要变更同一状态
(简单点说,vuex的作用就相当于一个存储室,将数据(状态)存在其中,当组件要用的时候,就从这里面拿;当一个组件修改里面的内容后,其他组件访问到的是修改后的内容)
vuex工作原理
官方原理图
(1)vuex有三个主要的对象,State(状态),Actions(动作),Mutations(变更),他们都由Store对象进行管理,用的时候要用Store进行调用。
State(状态):用于存储数据,相当于组件中的data
Actions(动作):用于响应组件中的动作,相当于组件中的method,可以处理异步操作
Mutations(变更):用于操作数据,同样相当于组件中的method,只可以处理同步操作
(2)一般在Actions中可以进行逻辑处理和异步操作,例如判断传过来的数是不是奇数,axios异步获取数据等。
(3)Mutations中必须是同步操作,其中的方法是唯一能够修改 State 数据的地方,如果 Mutation 中的方法是异步的,那么就无法保证 State 的改变是同步的,所有只需要直接操作 State 对象即可。
(4)当Actions和mutations中的方法执行代码一样时,可以略过Actions中的dispatch方法,直接使用commit方法。
(5)使用vuex管理数据说的就是将数据交给vuex中的State对象进行管理
2、配置vuex环境和使用
(1)安装:npm i vuex
,需要注意的是vue2要用vuex3版本,vue3要用vuex4版本,要@符号指定版本
(2)在src下创建文件夹,取名store,其下在创建一个index.js文件,内容如下:
- 该文件用于创建Vuex中最为核心的store
// 引入vuex
import Vue from 'vue'
import Vuex from 'vuex'const actions = {}
const state = {}
const mutations = {}// 在这里使用vuex
Vue.use(Vuex)// 创建并暴露store
export default new Vuex.Store({state:state,actions:actions,mutations:mutations
})
(3)在main.js引入store,添加store配置项,如下
import Vue from 'vue'
import App from './App.vue'
import store from './store/index'Vue.config.productionTip = falsenew Vue({render: h => h(App),store:store,
}).$mount('#app')
(4)组件中读取vuex中的数据:$store.state.sum
(5)组件中修改vuex中的数据:$store.dispatch(‘action中的方法’,数据)或$store.commit(‘mutations中的方法’,数据)
补充:若没有网络要求或其他业务逻辑,组件中也可以越过actions,即不写dispatch,直接编写commit
使用案例
普通方式实现:
- App.vue
<template><div><Count></Count></div>
</template><script>import Count from './components/Count.vue'export default {name:"App",components:{Count}}
</script>
- count.vue
<template><div><h2>当前求和为{{sum}}</h2><select v-model.number=n><option value="1">1</option><option value="2">2</option><option value="3">3</option></select><button @click="increment">+</button><button @click="decrement">-</button><button @click="incrementOdd">当前和为奇数时再加</button><button @click="incrementWait">等一等再加</button></div>
</template><script>
export default {name:"Count",data(){return {n:1,sum:0,}},methods:{increment(){this.sum += this.n},decrement(){this.sum -= this.n},incrementOdd(){if(this.sum % 2){this.sum += this.n}},incrementWait(){setTimeout(()=>{this.sum += this.n},500)}}
}
</script>
vuex实现,将sum作为共享的数据放入vuex中
- App.vue
<template><div><Count></Count></div>
</template><script>import Count from './components/Count.vue'export default {name:"App",components:{Count}}
</script>
- count.vue
<template><div><h2>当前求和为{{$store.state.sum}}</h2><select v-model.number="n"><option value="1">1</option><option value="2">2</option><option value="3">3</option></select><button @click="increment">+</button><button @click="decrement">-</button><button @click="incrementOdd">当前和为奇数时再加</button><button @click="incrementWait">等一等再加</button></div>
</template><script>
export default {name: "Count",data() {return {n: 1,};},methods: {// $store中有要用到的dispatch,commit等方法increment() {this.$store.dispatch('add',this.n)},decrement() {// 跳过调用dispatch方法,直接调用commit方法this.$store.commit('SUB',this.n) // 直接和mutations交互,那么方法名要和mutations中的一致},incrementOdd() {this.$store.dispatch('addOdd',this.n)},incrementWait() {this.$store.dispatch('addWait',this.n)},},
};
</script><style>
</style>
- index.js
// 引入vuex
import Vue from 'vue'
import Vuex from 'vuex'
// 该文件用于创建Vuex中最为核心的store// 共享的数据放在state中
const state = {sum: 0,
}const actions = {// dispatch传过来的方法add(context,value){// console.log(context,value); // 结果是vc和传过来的参数值// 在actions中调用commit方法,将ADD传给mutationscontext.commit("ADD",value)},// sub方法直接跳过调用dispatch方法// sub(context,value){// context.commit("SUB",value)// },addOdd(context,value){// 进行逻辑判断if(context.state.sum % 2){context.commit('ADDODD',value)}},addWait(context,value){// 添加个定时器setTimeout(()=>{context.commit('ADDWAIT',value)},500)}}const mutations = {// 这里的add和ADD其实是一个,只是用于区分所在位置而改个大小写ADD(state,value){state.sum += value},SUB(state,value){state.sum -= value},ADDODD(state,value){state.sum += value},ADDWAIT(state,value){state.sum += value}
}// 在这里使用vuex插件
Vue.use(Vuex)// 创建并暴露store
export default new Vuex.Store({state: state,actions: actions,mutations: mutations
})
3、getter配置项
1、当state中的数据需要经过加工后再使用时,可以使用getters加工(相当于vue中的计算属性)。
2、在index.js中追加getters配置
const getters = {bigSum(state){return state.sum * 10}
}// 创建并暴露store
export default new Vuex.Store({...getters
})
3、组件中读取数据:$store.getters.bigSum
5、四个map方法的使用
使用前要导入相关包
import {mapState,mapGetters,mapActions,mapMutations} from 'vuex'
- mapState方法
用于帮助映射state中的数据为计算属性
// html结构上使用计算属性表示
<h3>{{sum}}</h3>
<h3>{{school}}</h3>
....
//=================computed :{// (1)手写计算属性时sum(){return this.$store.state.sum // sum是state上的数据}school(){return this.$store.state.school // shool也是state上的数据}// (2)使用mapState简化步骤// 对象写法...mapState({sum:'sum',shool:'school'})// 数组写法(注意这种写法下计算属性名要和state上的属性名一致...mapState(['sum','school'])
}
- mapGetters方法
用于帮助映射getters中的数据为计算属性
// 下面的属性是getters中的
<h3>{{bigSum}}</h3>
...
//=================computed :{// (1)手写计算属性时bigSum(){return this.$store.getters.bigSum }// (2)使用mapGetters简化步骤// 对象写法...mapGetters({bigSum:'bigSum'})// 数组写法(注意这种写法下计算属性名要和getters上的属性名一致...mapGetters(['bigSum'])
- mapActions方法
用于帮助生成与actions对话的方法,即包含$stroe.dispatch(xxx)
的函数
<button @click="increment(参数)">{{add}}</button>
<button @click="decrement(参数)">{{sub}}</button>
...//=================
methods:{// 普通方式下increment(){this.$store.dispatch('add',传进来的参数)}decrement(){this.$store.dispatch('sub',传进来的参数)}// 使用mapActions简化步骤// 对象写法// 借助mapActions生成对应的方法,方法中会调用dispatch去联系Actions...mapActions({increment:"add",decrement:"sub"})// 数组写法(要求dispatch中的方法传递的方法要和调用dispatch的回调方法名一致时才能使用)...mapActions(['add','bub'])
}
需要注意的是如果有传递参数需要,则要在模板中绑定事件时传递好参数,否则参数时事件对象
- mapMutations方法
用于帮助生成mutations对话的方法,即包含$store.commit(xxx)
的函数
<button @click="increment(参数)">{{add}}</button>
<button @click="decrement(参数)">{{sub}}</button>
...//=================
methods:{// 普通方式下increment(){this.$store.commit('add',传进来的参数)}decrement(){this.$store.commit('sub',传进来的参数)}// 使用mapMutations简化步骤// 对象写法// 借助mapMutations生成对应的方法,方法中会调用commit去联系Mutations...mapMutations({increment:"add",decrement:"sub"})// 数组写法(要求commit中的方法传递的方法要和调用commit的回调方法名一致时才能使用)...mapMutations(['add','bub'])
}
需要注意的是如果有传递参数需要,则要在模板中绑定事件时传递好参数,否则参数会代表事件对象,例如鼠标事件对象。
6、vuex模块化+命名空间
1、模块化目的:让代码更好维护,让数据分类更加明确
2、具体操作
(1)将state、mutations、actions、getters按照分类(不同组件)分类好,放到各自的一个对象中,并且在对象中添加一个配置项namespaced:true
,用于给所属模块开启命名空间。
const countAbout = {namespaced: true, // 开启命名空间state: {x:1},mutations: { ... },actions: { ... },getters: {bigSum(state){ return state.sum * 10 }}
}const personAbout = {namespaced: true, // 开启命名空间state: { ... },mutations: { ... },actions: { ... }
}const store = new Vuex.Store({modules: {countAbout,personAbout}
})
(2)开启命名空间后
1)组件读取state中数据的方式
// 方式一:自己直接读取
this.$store.state.personAbout.list
// 方式二:借助mapState读取(第一个参数countAbou在第(1)步中的对象开启命名空间后才能使用)
...mapState('countAbout',['sum','school','subject']),
2)组件读取getters中数据的方式
//方式一:自己直接读取
this.$store.getters['personAbout/firstPersonName']//方式二:借助mapGetters读取:
...mapGetters('countAbout',['bigSum'])
3)组件读取Actions中数据的方式
//方式一:自己直接dispatch
this.$store.dispatch('personAbout/addPersonWang',person)//方式二:借助mapActions:
...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
4)组件中读取Mutations中数据的方式
//方式一:自己直接commit
this.$store.commit('personAbout/ADD_PERSON',person)//方式二:借助mapMutations:
...mapMutations('countAbout',{increment:'JIA',decrement:'JIAN'}),