Vue 学习笔记 01——iview
Vue 学习笔记 02
Vue 学习笔记 03——组件篇
Vue 学习笔记 04——TabPanel
Vue 学习笔记 05——状态管理Vuex
===================================正文分割线==================================
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。流程如下官网图所示:
Vuex 的核心就是 store(仓库),它就像一个容器,包含着应用中大部分的状态 state .Vuex与全局对象的不同在于:
1)Vuex状态存储为响应式的,store中的状态发生改变时,相应的组件也会更新
2)不能直接改变store中的state,唯一途径是显示的提交(commit)mutation。这样方便跟踪每一个状态的变化
1)在main.js中引入创建store
* 创建后可以通过 store.state 来获取状态对象,以及通过 store.commit 方法触发状态变更
import Vue from 'vue'
import Vuex from 'vuex'
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
}
})
2) 然后在Vue实例中,提供创建好的store,如此便可在组件中访问到this.$store中的property
new Vue({
el: '#app',
store: store,
})
3)现在可以在计算属性computed中,返回状态
computed:{
count(){
return this.$store.state.count;
}
}
4)当状态需要改变时,可通过在组件的 methods 中提交(commit) mutation
methods: {
increment() {
this.$store.commit('increment')
console.log(this.$store.state.count)
}
}
1)State
a)所有的状态定义在state对象中;
b)从 store 实例中 读取状态 最简单的方法就是在 计算属性 中返回某个状态;
c)Vuex提供一种机制将状态从根组件“注入”到每一个子组件中( 需要调用Vue.use(Vuex) ):
const app = new Vue({
el: '#app',
// 把 store 对象提供给 “store” 选项,这可以把 store 的实例注入所有的子组件
store,
components: { Counter },
template: `
`
})
通过根实例注册的store,改store实例会注入到根组件下的所有子组件,且子组件能通过this.$store访问到,如下:
const Counter = {
template: `{{ count }}`,
computed: {
count () {
return this.$store.state.count
}
}
}
d)辅助函数 mapState
当一个组件要获取多个状态的时候,可使用 mapState 辅助函数帮助我们生成计算属性,这样简洁一些。
当映射的计算属性的名称与 state 的子节点名称相同时,我们也可以给 mapState 传一个字符串数组。
import { mapState, mapGetters } from 'vuex'
...
computed:{
...mapState(['userInfo']),
...mapGetters(['memberInfo'])
},
...
2)Getter
可以理解为是获取数据的,有时候我们需要从 store 中的 state 中派生出一些状态,例如根据userState的值显示用户等级:
a)Getter 接受 state 作为其第一个参数
export default{
memberInfo(state){
switch (state.userStatus){
case 0:
return '普通会员';
break;
case 1:
return 'VIP会员';
break;
case 2:
return '高级V'+ state.vipLevel +'会员';
break;
default:
return '普通会员';
break;
}
}
}
b)使用时,也可用辅助函数 mapGetters
3)Mutation
a)它是更改 Vuex 的 store 中状态的唯一方法是提交 mutation. 而 mutation 类似一个事件,每一个 mutation 都有一个字符串的事件类型和一个回调函数,回调函数就是我们状态要进行更改的地方,并且它会接受 state 作为第一个参数。
b)Mutation 必须是同步函数
例如:登录后修改userStatus
//登录组件的login()中
//commit中有两个参数
//第一个参数,对应的是mutation中的函数名
//第二个参数,多数情况下是一个对象
self.$store.commit('setMemberInfo',{
userStatus:0,
vipLevel:0
});
//mutations.js中
export default{
//登录调用,重置用户信息
login(state, v){
state.userInfo = v;
},
//重新修改用户等级状态
//第一个参数接收state
//第二个参数接收组件中commit传来的值
setMemberInfo(state,v){
state.userStatus = v.userStatus;
state.vipLevel =v.vipLevel;
}
}
4)Action
Action 类似于 mutation,不同在于:
- Action 提交的是 mutation,而不是直接变更状态。
- Action 可以包含任意异步操作。
a)注册一个简单的 action:
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
},
actions: {
increment (context) {
context.commit('increment')
}
}
})
由于 Action函数 接收一个 与store实例具有相同方法和属性 的 context 对象,因此可以用context.commit来提交一个mutation,
而实践中,我们会经常用到 ES2015 的 参数解构 来简化代码(特别是我们需要调用 commit
很多次的时候),如下案例:
actions: {
increment ({ commit }) {
commit('increment')
}
}
//actions.js中
export default{
//分发的时候有传值的情况
buyVip({commit},e){
//mock api交互
return new Promise((resolve,reject)=>{
setTimeout(()=>{
//修改本地state
commit('setMemberInfo',{
userStatus:e.userStatus,
vipLevel:e.vipLevel
})
resolve('购买成功')
},1000)
})
},
//分发的时候无值,但需要使用state的情况
getFreeVip({commit,state}){
//mock api 交互
return new Promise(function(resolve,reject) {
setTimeout(function(){
if(state.userStatus === 0){
//仅限普通会员才能分享获得高级会员资格
commit('setMemberInfo',{
userStatus:1,
vipLevel:0
});
resolve('分享成功,您已获得一个月的高级vip');
}else{
resolve('分享成功');
}
},1000)
})
}
}
b)通过 dispatch 分发 action:
store.dispatch可以处理被触发的action函数返回的Promise,并且仍旧返回Promise,如下:
methods:{
buy:function(e){
//正常是与后台交互,传递会员信息与购买缴费
//此处是本地数据的处理
//第一个参数是actions.js中的函数名
//第二个参数是需要传的值
store.dispatch('buyVip',e).then(res=>{
alert(res);
})
}
}