VueX使用备忘(含Vuex实例和Vuex模块化)

VueX使用备忘

1. Vuex 介绍

Vuex 是专门为 Vue应用程序开发的状态管理模式,
它采用集中式存储管理应用的所有组件状态,
并以相应的规则保证状态以一种可预测的方式发生变化。
可以理解为:将多个组件共享的变量全部存储在一个对象里面,
然后将这个对象放在顶层的 Vue 实例中,
让其他组件可以使用,它最大的特点是响应式。

一般情况下,我们会在 Vuex 中存放一些需要在多个界面中进行共享的信息。
比如用户的登录状态、用户名称、头像、地理位置信息、商品的收藏、购物车中的物品等,
这些状态信息,我们可以放在统一的地方--Vuex,对它进行保存和管理;

2. Vuex 插件的安装

// 安装时记的带上@版本号,  Vue2-vuex3,  Vue3-vuex4
//			注意: vue2.x 版本对应 vuex 3.x 版本,vue3.x版本对应 vuex 4.x 版本
//		不加@版本号,则默认安装最新的vuex,会造成Vue2等较低版本无法使用vuex功能;
npm install --save vuex@3.6.2

3. Vuex环境的搭建

store 对象中存放的东西是固定的,
	主要有:state、mutations、actions、getters、modules
下图为官方给出的vuex状态管理图例:

在这里插入图片描述

3-1 src下新建store文件夹,创建 index.js,引入/安装/创建并导出Vuex

import Vue from 'vue'
import Vuex from 'vuex'
//1.安装插件
Vue.use(Vuex)
//2.创建对象
const store = new Vuex.Store({
  state:{
    counter:1000
  },
  mutations:{
 
  },
  actions:{
 
  },
  getters:{
 
  },
  modules:{
    
  }
})
//3.导出使用
export default store

3-2 在 main.js中挂载使用

import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store'  // 导入Vuex
 
Vue.config.productionTip = false
 
/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  store,	// 使用Vuex
  render: h => h(App)
})

3-3 Vuex的基本使用

1. 获取state的状态[数据]:state中存放需要共享的状态[数据]信息,
	使用时通过 $store.state.counter 即可拿到状态[数据]信息
2. 修改state的状态[数据]:
	获取store对象,通过 commit 提交 mutations 中的方法
	如:Vue中使用实例:
		methods:{
			sub(){
				this.$store.commit("decrement")
			},
			add(){
				this.$store.commit("increment")
			}
		}
3. devtools 开发工具的调试界面,可以跟踪查看每一次事件操作,此处不赘述了		

4. Vuex 中各配置项详解及使用实例

4-1 State

单一状态树即单一数据源,
在一个项目中只使用一个store对象,
来存储所有共享的状态信息

4-2 Getters

// 类似于Vue中计算属性computed,
// 		在数据展示前进行一些变化处理,
//		具有缓存功能,能够提高运行效率
// 比如:
  getters:{
  	// 直接使用state中的状态[数据]计算
    powerCounter(state){
      return state.counter * state.counter
    },
    // 过滤出state中的符合条件的数据信息
    more20stu(state){
      return state.students.filter(s => s.age > 20)
    },
    // 已有getters的复用--用到了上方的more20stu
    more20stuLength(state,getters){
      return getters.more20stu.length
    },
    // 带参数的getters
    moreAgeStu(state){
      return function(age){
        return state.students.filter(s => s.age > age)
      }
    }
  }

// 使用时通过:$store.getters.powerCounter 获取
    <h2>{{$store.getters.powerCounter}}</h2>
    <h2>{{$store.getters.more20stu}}</h2>
    <h2>{{$store.getters.more20stuLength}}</h2>
    <h2>{{$store.getters.moreAgeStu(18)}}</h2>

4-3 Mutations

4-3-1 Mutations自定义方法实例
  mutations:{//定义一些方法
    increment(state){
      state.counter++
    },
    decrement(state){
      state.counter--
    },
    incrementCount(state, payload){
      //1.普通提交方式
      //state.counter += count
      //2.特殊提交方式 ,第二个参数是一个对象
      state.counter += payload.count
    },
    addStudent(state, obj){
      // 给state中的students数组,增加一个对象obj
      state.students.push(obj)
    }
  }
4-3-2 Vue组件使用mutations的实例
<template>
  <div>
    <button @click="addCount(5)">+5</button>
    <button @click="addCount(10)">+10</button>
    <button @click="addStudent({id:105, name:'name6', age:29})">添加学生</button>
  </div>
</template>
 
<script>
export default {
  name:"HelloVuex",
  methods:{
    addCount(count){
      //1.普通的提交风格
      // this.$store.commit('incrementCount',count)
      //2.特殊的提交风格,commit参数为一个对象,type-mutations中的方法名,count-自定义的参数
      this.$store.commit({
        type:'incrementCount',
        count:count
      })
    },
    addStudent(stu){
      this.$store.commit('addStudent',stu)
    }
  }
}
</script>
 
<style>
</style>

4-4 Actions

4-4-1 实例1
//	如果需要进行一些异步操作,
//		比如网络请求,建议在 Actions 中进行处理,
//		这样 devtools 就能够进行跟踪,
//		由 Actions 处理异步操作,
//	具体的函数部分,仍交由 Mutations 进行处理
  actions:{
    // context: 上下文 === store[相当于小型迷你的store]
    // payload:为$store.dispatch传递过来的参数
    aUpdateInfo(context,payload){
      setTimeout(() => {
        context.commit('updateInfo',payload)
        console.log(payload);
      }, 5000);
    }
  }


// Vue组件中使用时,调用:this.$store.dispatch('aUpdateInfo') 
    updateInfo(){
      // this.$store.commit('updateInfo')  			// 无参数
      this.$store.dispatch('aUpdateInfo','参数')	// 有参数, 参数可以是对象、数组等
    }
4-4-2 实例2
  // 结合Promise使用:
  actions:{
    //context:上下文 === store
    aUpdateInfo(context, payload){
      return new Promise((resolve, reject)=>{
        setTimeout(() => {
          context.commit('updateInfo');
          console.log(payload);
          resolve('11111')
        }, 1000);
      })
    }
  }

// Vue组件中使用:
methods:{
	updateInfo(){
      this.$store
      .dispatch('aUpdateInfo','参数')
      .then(res =>{
        console.log('里面完成了提交');
        console.log(res);
      })
    }
}

5. 多组件共享数据实例_天禹老师Vue教程中演示

5-1 实例图形展示

在这里插入图片描述

5-2 实例具体代码

5-2-1 实例相关说明
本例有两个组件,分别是,
	Count组件, 详见Count.vue。
	Person组件,详见Person.vue。
Count组件和Person组件共享以下两个数据[存储在state中,名称自定义的]:
	sum ,
	personList
	
代码主要涉及如下几个文件,
	main.js,本例中不涉及变更。
	App.vue,本例不涉及变更。
	store/index.js,本例中,会发生多次变更。
	Person.vue,本例中,会发生多次变更。
	Count.vue,本例中,会发生多次变更。
5-2-2 main.js
import Vue from 'vue'
import App from './App.vue'
import store from "./store";
Vue.config.productionTip = false

const vm = new Vue({
  render: h => h(App),
  store  // 使用Vuex
}).$mount('#app');
console.log(vm);
5-2-3 App.vue
<template>
  <div id="app">
    <Count/>
    <hr>
    <Person/>
  </div>
</template>

<script>
import Count from './components/Count.vue';
import Person from './components/Person.vue';

export default {
  name: 'App',
  components: {
    Count,
    Person
  }
}
</script>
5-2-4 store/index.js
import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);

const state = {
    sum:0,
    personList:[
        {id:"001",name:"张三"}
    ]
};

const getters = {
    bigSum(state){
        return state.sum*10;
    }
}

const actions = {
    jiaOdd(context,value){
        if(context.state.sum  % 2){
            context.commit("JIA",value);
        }
    },
    jiaWait(context,value){
        setTimeout(() => {
            context.commit("JIA",value);
        },500)
    }

};

const mutations = {
    JIA(state,value){
        state.sum += value;
    },
    JIAN(state,value){
        state.sum -= value;
    },
    ADD_PERSON(state,personObj){
        state.personList.unshift(personObj);
    }
};

export default new Vuex.Store({
    state,
    getters,
    actions,
    mutations
})
5-2-5 Person.vue
<template>
  <div>
      <h2>人员列表</h2>
      <h3 style="color:red">Count组件的当前和为{{sum}}</h3>
      <input type="text" placeholder="请输入姓名" v-model="name"/>
      <button @click="add">添加</button>
      <ul>
          <li v-for="p in personList" :key="p.id">{{p.name}}</li>
      </ul>
  </div>
</template>

<script>
import {nanoid} from "nanoid";
export default {
    name:"Person",
    data(){
        return {
            name:""
        }
    },
    computed:{
        personList(){
            return this.$store.state.personList;
        },
        sum(){
            return this.$store.state.sum;
        }
    },
    methods: {
        add(){
            const personObj = {
                id:nanoid(),
                name:this.name
            }
            this.$store.commit("ADD_PERSON",personObj);
            this.name = "";
        }
    }
}
</script>

<style scoped>
button{
    margin-left: 5px;
}
</style>
5-2-6 Count.vue
<template>
  <div class="count">
    <h2>当前求和为{{sum}}</h2>
    <h2>当前求和放大10倍为{{bigSum}}</h2>
    <h3 style="color:red">Person组件的总人数为{{personList.length}}</h3>
    <select v-model="num">
      <option :value="1">1</option>
      <option :value="2">2</option>
      <option :value="3">3</option>
    </select>
    <button @click="increment(num)">+</button>
    <button @click="decrement(num)">-</button>
    <button @click="incrementOdd(num)">和为奇数时再加</button>
    <button @click="incrementWait(num)"> 等一等再加</button>
  </div>
</template>

<script>
import {mapState,mapGetters,mapActions,mapMutations} from "vuex";
export default {
  name: 'Count',
  data(){
    return {
      num:1
    }
  },
  computed:{
    ...mapState(["sum","company","position","personList"]),
    ...mapGetters(["bigSum"])
  },
  methods: {
    ...mapActions({
      incrementOdd:"jiaOdd",
      incrementWait:"jiaWait"
    }),
    ...mapMutations({
      increment:"JIA",
      decrement:"JIAN"
    })
  }
}
</script>

<style scoped>
  button{
    margin-left: 5px;
  }
</style>

6. Vuex模块化实例一 – 模块不带命名空间

6-1 store/person/index.js – person模块的store

const state = {
    personList:[
        {id:"001",name:"张三"}
    ]
}

const getters = {}

const actions = {}

const mutations = {
    ADD_PERSON(state,personObj){
        state.personList.unshift(personObj);
    }
}

export default {
    state,
    getters,
    actions,
    mutations
}

6-2 store/count/index.js

const state = {
    sum:0
}

const getters = {
    bigSum(state){
        return state.sum*10;
    }
}

const actions = {
    jiaOdd(context,value){
        if(context.state.sum  % 2){
            context.commit("JIA",value);
        }
    },
    jiaWait(context,value){
        setTimeout(() => {
            context.commit("JIA",value);
        },500)
    }
}

const mutations = {
    JIA(state,value){
        state.sum += value;
    },
    JIAN(state,value){
        state.sum -= value;
    }
}

export default {
    state,
    getters,
    actions,
    mutations
}

6-3 store/index.js

// 说明:
// 		Count组件相关的state、getters、actions、mutations独立成模块store/count/index.js;
// 		Person组件相关的state、getters、actions、mutations独立成模块store/person/index.js。
// 		store/index.js中导入以上两个模块,并通过modules聚合,即:
// 			new Vuex.Store({modules:{countAbout,personAbout}})。
import Vue from "vue";
import Vuex from "vuex";
import countAbout from "./count";
import personAbout from "./person";

Vue.use(Vuex);

export default new Vuex.Store({
	// Vuex导入上方两个模块,countAbout、personAbout,分别相当于一个$store
    modules:{
        countAbout,
        personAbout
    }
})

6-4 Person.Vue

<template>
  <div>
      <h2>人员列表</h2>
      <h3 style="color:red">Count组件的当前和为{{sum}}</h3>
      <input type="text" placeholder="请输入姓名" v-model="name"/>
      <button @click="add">添加</button>
      <ul>
          <li v-for="p in personList" :key="p.id">{{p.name}}</li>
      </ul>
  </div>
</template>

<script>
import {nanoid} from "nanoid";
export default {
    name:"Person",
    data(){
        return {
            name:""
        }
    },
    computed:{
        personList(){
        	// 直接访问Vuex中模块personAbout的数据personList
            return this.$store.state.personAbout.personList;
        },
        sum(){
        	// 直接访问Vuex中模块countAbout的数据sum
            return this.$store.state.countAbout.sum;
        }
    },
    methods: {
        add(){
            const personObj = {
                id:nanoid(),
                name:this.name
            }
            // 可直接访问countAbout中的mutations方法ADD_PERSON,[没有使用命名空间
            this.$store.commit("ADD_PERSON",personObj);
            this.name = "";
        }
    },
}
</script>

<style scoped>
	button{
	    margin-left: 5px;
	}
</style>

6-5 Count.vue

6-5-1 mapState,mapGetters,mapActions,mapMutations的对象写法
<template>
  <div class="count">
    <h2>当前求和为{{sum}}</h2>
    <h2>当前求和放大10倍为{{bigSum}}</h2>
    <h3 style="color:red">Person组件的总人数为{{personList.length}}</h3>
    <select v-model="num">
      <option :value="1">1</option>
      <option :value="2">2</option>
      <option :value="3">3</option>
    </select>
    <!-- 这里调用的方法,为Vuex的mapXxx映射而来,
    		如有参数,此处必须传入, 
			否则,Vuex中对应方法获取到的就是当前Vue的$event了;
	-->
    <button @click="increment(num)">+</button>
    <button @click="decrement(num)">-</button>
    <button @click="incrementOdd(num)">和为奇数时再加</button>
    <button @click="incrementWait(num)"> 等一等再加</button>
  </div>
</template>

<script>
import {mapState,mapGetters,mapActions,mapMutations} from "vuex";
export default {
  name: 'Count',
  data(){
    return {
      num:1
    }
  },
  computed:{
    ...mapState({
      // 自动映射一个计算属性为sum,对应到Vuex模块的state.countAbout.sum
      sum:state => state.countAbout.sum,
      // 自动映射一个计算属性为personList,对应到Vuex模块的state.personAbout.personList
      personList:state => state.personAbout.personList
    }),
      // 映射一个计算属性为bigSum,来自state.countAbout.getters中的bigSum
    ...mapGetters(["bigSum"])
  },
  methods: {
  	// 映射state.countAbout.Actions中的jiaOdd、jiaWait方法
  	// 	并对方法重新取名为incrementOdd,incrementWait,供Vue页面中使用
    ...mapActions({
      incrementOdd:"jiaOdd",
      incrementWait:"jiaWait"
    }),
    ...mapMutations({
      increment:"JIA",
      decrement:"JIAN"
    })
  }
}
</script>

<style scoped>
  button{
    margin-left: 5px;
  }
</style>
6-5-2 mapState,mapGetters,mapActions,mapMutations的数组写法
<template>
  <div class="count">
    <h2>当前求和为{{countAbout.sum}}</h2>
    <h2>当前求和放大10倍为{{bigSum}}</h2>
    <h3 style="color:red">Person组件的总人数为{{personAbout.personList.length}}</h3>
    <select v-model="num">
      <option :value="1">1</option>
      <option :value="2">2</option>
      <option :value="3">3</option>
    </select>
    <button @click="JIA(num)">+</button>
    <button @click="JIAN(num)">-</button>
    <button @click="jiaWait(num)">和为奇数时再加</button>
    <button @click="jiaWait(num)"> 等一等再加</button>
  </div>
</template>

<script>
import {mapState,mapGetters,mapActions,mapMutations} from "vuex";
export default {
  name: 'Count',
  data(){
    return {
      num:1
    }
  },
  computed:{
    // 自动将Vuex中的countAbout和personAbout映射为计算属性
    //	且名和Vuex中的mudules模块名一致: countAbout、personAbout,Vue中直接使用
    ...mapState(["countAbout","personAbout"]),
    ...mapGetters(["bigSum"])
  },
  methods: {
    // Actions和Mutations中的方法,自动映射为Vue可用的同名方法
    ...mapActions(["jiaOdd","jiaWait"]),
	...mapMutations(["JIA","JIAN"]),
  }
}
</script>

<style scoped>
  button{
    margin-left: 5px;
  }
</style>

7. Vuex模块化实例二 – 模块带命名空间[推荐使用]

7-1 store/person/index.js

// Person组件的state、getters、actions、mutations独立成模块:
//		store/person/index.js,且该模块带命名空间:  namespaced:true
const state = {
    personList:[
        {id:"001",name:"张三"}
    ]
}
const getters = {}
const actions = {}
const mutations = {
    ADD_PERSON(state,personObj){
        state.personList.unshift(personObj);
    }
}
export default {
    namespaced:true,  // 加上该配置项,则启用了命名空间
    state,
    getters,
    actions,
    mutations
}

7-2 store/count/index.js

// Count组件相关的state、getters、actions、mutations独立成模块;
//	store/count/index.js,且该模块带命令空间:namespaced:true。
const state = {
    sum:0
}
const getters = {
    bigSum(state){
        return state.sum*10;
    }
}
const actions = {
    jiaOdd(context,value){
        if(context.state.sum  % 2){
            context.commit("JIA",value);
        }
    },
    jiaWait(context,value){
        setTimeout(() => {
            context.commit("JIA",value);
        },500)
    }
}
const mutations = {
    JIA(state,value){
        state.sum += value;
    },
    JIAN(state,value){
        state.sum -= value;
    }
}
export default {
    namespaced:true,
    state,
    getters,
    actions,
    mutations
}

7-3 store/index.js

//	带命名空间的模块:
//	store/person/index.js
//	store/count/index.js
//		通过modules在store/index.js中聚合
import Vue from "vue";
import Vuex from "vuex";
import countAbout from "./count";
import personAbout from "./person";

Vue.use(Vuex);

export default new Vuex.Store({
    modules:{
        countAbout,
        personAbout
    }
})

7-4 Person.vue

<template>
  <div>
      <h2>人员列表</h2>
      <h3 style="color:red">Count组件的当前和为{{sum}}</h3>
      <input type="text" placeholder="请输入姓名" v-model="name"/>
      <button @click="add">添加</button>
      <ul>
          <li v-for="p in personList" :key="p.id">{{p.name}}</li>
      </ul>
  </div>
</template>

<script>
import {nanoid} from "nanoid";
export default {
    name:"Person",
    data(){
        return {
            name:""
        }
    },
    computed:{
        personList(){
        	// 获取指定模块personAbout的personList
            return this.$store.state.personAbout.personList;
        },
        sum(){
            // 获取指定模块countAbout的sum
            return this.$store.state.countAbout.sum;
        }
    },
    methods: {
        add(){
            const personObj = {
                id:nanoid(),
                name:this.name
            }
            // 调用指定模块personAbout的方法ADD_PERSON,参数为personObj
            this.$store.commit("personAbout/ADD_PERSON",personObj)
            this.name = "";
        }
    }
}
</script>

<style scoped>
button{
    margin-left: 5px;
}
</style>

7-5 Count.vue

<template>
  <div class="count">
    <h2>当前求和为{{sum}}</h2>
    <h2>当前求和放大10倍为{{bigSum}}</h2>
    <h3 style="color:red">Person组件的总人数为{{personList.length}}</h3>
    <select v-model="num">
      <option :value="1">1</option>
      <option :value="2">2</option>
      <option :value="3">3</option>
    </select>
    <button @click="increment(num)">+</button>
    <button @click="decrement(num)">-</button>
    <button @click="incrementOdd(num)">和为奇数时再加</button>
    <button @click="incrementWait(num)"> 等一等再加</button>
  </div>
</template>

<script>
import {mapState,mapGetters,mapActions,mapMutations} from "vuex";
export default {
  name: 'Count',
  data(){
    return {
      num:1
    }
  },
  computed:{
    // 分别映射模块countAbout的sum,personAbout的personList的state状态[数据]
    ...mapState("countAbout",["sum"]),
    ...mapState("personAbout",["personList"]),

	// 映射countAbout模块的getters配置项bigSum
    ...mapGetters("countAbout",["bigSum"])

	// ==========================================================
	//	1. 直接将模块映射至Vue页面中,仍可直接访问模块的数据和方法
	// ...mapState(["countAbout","personAbout"]),

	//	2. 和不带命名空间时使用的方式,仍可获取不同模块的state的值,
	//		指定对应的state和目标模块的state的值了
    // ...mapState({
    //   sum:state => state.countAbout.sum,
    //   personList:state => state.personAbout.personList
    // }),

	// 3. 直接访问countAbout模块的state:sum
    // sum(){
    //   return this.$store.state.countAbout.sum;
    // },
    //	4. 直接访问personAbout模块的state:personList
    // personList(){
    //   return this.$store.state.personAbout.personList;
    // },
    //	5. 直接访问countAbout模块的getters:bigSum
    // bigSum(){
    //   return this.$store.getters["countAbout/bigSum"]
    // }
    // ==========================================================
  },
  methods: {
  	// 映射countAbout模块的Actions中方法jiaOdd,jiaWait,
  	//	并通过对象方式重命名方法名,Vue中通过incrementOdd和incrementWait调用
    ...mapActions("countAbout",{
      incrementOdd:"jiaOdd",
      incrementWait:"jiaWait"
    }),
    
    // 映射countAbout模块的Mutations中方法JIA,JIAN
    ...mapMutations("countAbout",{
      increment:"JIA",
      decrement:"JIAN"
    }),

	// 	===========================================================
	// 	如下为直接发起Actions、Mutations中的方法,需带上模块名/模块方法名
	//		*******Actions中的方法
    // incrementOdd(){
    //   this.$store.dispatch("countAbout/jiaOdd",this.num)
    // },
    // incrementWait(){
    //   this.$store.dispatch("countAbout/jiaWait",this.num)
    // },

	//		*******Mutations中的方法
    // increment(){
    //   this.$store.commit("countAbout/JIA",this.num);
    // },
    // decrement(){
    //   this.$store.commit("countAbout/JIAN",this.num);
    // }
    // 	===========================================================
  }
}
</script>

<style scoped>
  button{
    margin-left: 5px;
  }
</style>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值