Vue 学习总结笔记 (十)
1. Vuex插件2. 搭建Vuex环境3. Vuex实现 求和案例4. Vuex的开发者工具5. Vuex中的 getters配置项6. Vuex中的 四个map方法7. Vuex的模块化(namespaced)7.1 Vuex的模块化7.2 针对map方法的 namespaced配置7.3 对于不使用map方法 ,程序员自己commit,dispatch,如何找到对应的模块。8. vuex模板
文章目录
1. Vuex插件
1.1 什么是Vuex?
概念:专门在Vue中实现集中式状态(数据)管理的一个Vue的插件。
- 与集中式对应的就是分布式。
- 对vue应用中多个组件的共享撞他进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间的通信。
1.2 为什么要用Vuex?
全局事件总线的一个对组件数据的读写效果:
实现读,需要一对$emit ,$on ;同样需要些也是需要一对$emit ,$on。如果多个组件都要对数据进行读写操作,那样用全局事件总线来解决这个问题就太麻烦了!!
Vuex就弥补了上面的问题:
什么时候使用Vuex?
- 多个组件的共享状态(数据)的读写操作。
1.3 Vuex的原理图
Vuex的相关结构:
- Actions(行动):看似是一个传递效果,其实它可以发送ajax请求,拿到接口相关的数据的。
- Mutations(转变,修改):负责修改State状态,也就是数据。
- State(状态 ):状态 , 在这里本质就是数据对象。
- 上面三个本质都是对象,Actions对象,Mutations对象。State对象。
上面各个函数很重要,像dispatch函数和commit函数都是开发人员自己直接可以调用的;而mutate和render是vue自主调用的函数。
Vuex中的Actions是可以跳过的:
Vuex的store,store是Actions,Mutations,State三个对象的管理者。
- 像store.dispatch和store.commit都是调用store身上的方法。
2. 搭建Vuex环境
2.1 安装Vuex的注意事项
在2022年2月7日,vue3成为了默认版本。
也就是说我们现在执行npm i vue命令 , 安装的直接就是vue3了。
- vue3成为了默认版本的同时,vuex也更新到了4版本。4版本的vuex只能适用于vue3。
- 再安装npm i vuex , 安装的就是vuex4版本。
- 因此,对于vue2项目,我们不能直接执行npm i vuex,因为,4版本的vuex不适用于vue2。如下图错误:
简而言之就是,vue2要用vuex的3版本。vue3要用vuex的4版本。
- 所以对于vue2版本,执行npm i vuex@3 严格指定版本号!
2.2 搭建Vuex环境
第一步:执行npm i vuex@3 命令(这里我们使用的vue2版本项目)。
第二步:Vue.use(Vuex) 引入vuex插件。
一旦使用了Vuex的插件,我们就可以在vm实例对象或者vc实例对象上面,添加一个store配置项。
之后,我们都是通过store配置项来操作。
第三步:创建文件src/store/index.js(官方推荐) , 也有src/vuex/store.js。见到store就必须知道!
第四步:修改index.js文件。
// 该文件用于创建Vuex中最为核心的store
//引入Vue,使用插件
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//引入Vuex的插件
//在这里使用use,就是为了防止出现一个before的错误。该错误见2.3 Vue的注意事项
Vue.use(Vuex)
// 准备actions 用于响应组件中的动作
const actions = {
}
// 准备mutations 用于操作数据(state状态)
const mutations = {
}
// 准备state 用于存储数据
const state = {
}
//创建store
const store = new Vuex.Store({
// actions:actions,
// mutations:mutations,
// state:state,
//简写为一下形式:
actions,
mutations,
state,
})
//对于当前文件我们要让外部文件使用,就必须要暴露相关信息。
//暴露store
export default store
//这样外部import导入的使用拿到的就是store这个对象
第五步:修改main.js导入我们设置的src/store/index.js文件。这样就可以在vm或者vc实例对象上面引用使用store配置项了。
import Vue from "vue"
import App from "./App.vue"
import vueResource from 'vue-resource'
//引入store
// import store from './store/index.js'
// 对于index.js,可以忽略的!因为vue会默认找index开头的。
import store from './store'
Vue.config.productionTip = false;
const vm = new Vue({
el:'#app',
render:h=>h(App),
// store:store,同样对象的简写形式。
store,
})
//打印查看。
console.log(vm)
store配置项就会多下面的一些内容:
2.3 Vue的注意事项
注意事项:
- 因为vue加载一个js文件,会先将所有import导入的文件加载完成,再去加载其他的信息。跟顺序没有关系。
因为上图这种问题,Vuex插件在use使用前,会报如下错误:
- 因为,Vue.use(vuex)使用插件js命令必须在new Vuex.Store({…})的使用对象的前面才可以。不然会报下图错误!
针对上面的错误解决办法就是将Vue.use()放到我们导入的文件,让他们的js代码执行顺序进行调整!!
2.4 Vuex的使用大体流程
Count.vue文件:
<template>
<div>
<!--
在模板中,我们不用使用this , 调用的$store就是this当前组件对象默认。
自然我们就能从state对象中拿到sum值。
-->
<h1>当前求和为:{{$store.state.sum}}</h1>
<select v-model="n">
<option :value="1">1</option>
<option :value="2">2</option>
<option :value="3">3</option>
</select>
<button @click="increment">+</button>
</div>
</template>
<script>
export default{
name:'Count',
data(){
return{
n:1,//用户选择的数字
}
},
methods:{
increment(){
this.$store.dispatch('jia',this.n)
}
},
}
</script>
<style scoped>
button{
margin-left: 5px;
}
</style>
src/store/index.js文件:
// 该文件用于创建Vuex中最为核心的store
//引入Vue,使用插件
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//引入Vuex的插件
//解决before的问题错误。
Vue.use(Vuex)
// 准备actions 用于响应组件中的动作
const actions = {
/*
对应的设置jia函数。
再次提醒这里的jia(){}是简写形式。本质就是jia:function(){}。
这里的两个参数context,value分别是:
context:一个携带部分功能的store(官方规定参数名是context上下文,实际上无所谓)。
value:发送过来的值。
*/
jia(context,value){
console.log("actions中的jia被调用了")
// console.log(context)
// console.log(value)
//将数据发送给mutations
context.commit('JIA',value)
}
}
// 准备mutations 用于操作数据(state状态)
const mutations = {
/*
同样对应actions的commit。
也携带了两个参数state和value:
state:就是Vuex中的state对象,
value:就是传过来的值。
在mutations中,对state对象进行操作。
*/
JIA(state,value){
console.log("mutations中的JIA被调用了")
// console.log(state)
// console.log(value)
//对state进行操作。
state.sum += value
}
}
// 准备state 用于存储数据
const state = {
sum:0//当前和
}
//创建store
const store = new Vuex.Store({
// actions:actions,
// mutations:mutations,
// state:state,
//简写为一下形式:
actions,
mutations,
state,
})
//对于当前文件我们要让外部文件使用,就必须要暴露相关信息。
//暴露store
export default store
//这样外部import导入的使用拿到的就是store这个对象
这样完成了对Vuex中state对象的sum的读写操作,流程也就是这样!
需要注意的是,对于数据或者一些业务逻辑,必须要添加到actions中,不能写到mutations中!!
- 一定分号层次,actions就是负责处理数据业务逻辑的。
- mutations就是负责修改state的数据的。
3. Vuex实现 求和案例
Count.vue组件:
<template>
<div>
<!--
在模板中,我们不用使用this , 调用的$store就是this当前组件对象默认。
自然我们就能从state对象中拿到sum值。
-->
<h1>当前求和为:{{$store.state.sum}}</h1>
<select v-model="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:{
increment(){
//对于没有业务逻辑的就不需要走actions了,我们直接commit就可以了。
this.$store.commit('JIA',this.n)
},
decrement(){
this.$store.commit('JIAN',this.n)
},
incrementOdd(){
this.$store.dispatch('jiaOdd',this.n)
},
incrementWait(){
this.$store.dispatch('jiaWait',this.n)
},
},
}
</script>
<style scoped>
button{
margin-left: 5px;
}
</style>
src/store/index.js文件:
// 该文件用于创建Vuex中最为核心的store
//引入Vue,使用插件
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//引入Vuex的插件
//解决before的问题错误。
Vue.use(Vuex)
// 准备actions 用于响应组件中的动作
const actions = {
/*
对应的设置jia函数。
再次提醒这里的jia(){}是简写形式。本质就是jia:function(){}。
这里的两个参数context,value分别是:
context:一个携带部分功能的store(官方规定参数名是context上下文,实际上无所谓)。
value:发送过来的值。
*/
jiaOdd(context,value){
console.log("actions中的jiaOdd被调用了")
if(context.state.sum % 2){
context.commit('JIAODD',value)
}
},
jiaWait(context,value){
console.log("actions中的jiaWait被调用了")
setTimeout(()=>{
context.commit('JIANWAIT',value)
},500)
}
}
// 准备mutations 用于操作数据(state状态)
const mutations = {
/*
同样对应actions的commit。
也携带了两个参数state和value:
state:就是Vuex中的state对象,
value:就是传过来的值。
在mutations中,对state对象进行操作。
*/
JIA(state,value){
console.log("mutations中的JIA被调用了")
// console.log(state)
// console.log(value)
//对state进行操作。
state.sum += value
},
JIAN(state,value){
console.log("mutations中的JIAN被调用了")
state.sum -= value
},
JIAODD(state,value){
console.log("mutations中的JIAODD被调用了")
state.sum += value
},
JIANWAIT(state,value){
console.log("mutations中的JIANWAIT被调用了")
state.sum += value
}
}
// 准备state 用于存储数据
const state = {
sum:0//当前和
}
//创建store
const store = new Vuex.Store({
// actions:actions,
// mutations:mutations,
// state:state,
//简写为一下形式:
actions,
mutations,
state,
})
//对于当前文件我们要让外部文件使用,就必须要暴露相关信息。
//暴露store
export default store
//这样外部import导入的使用拿到的就是store这个对象
4. Vuex的开发者工具
Vue和Vuex都是由vue团队打造出来的。
这个团队设计Vue的开发者工具中,也包含了Vuex的开发者工具。
图下,也符合了为什么官方认定的参数叫做context上下文的意思了。
5. Vuex中的 getters配置项
5.1 getters介绍和使用
getters的作用:当state中的数据需要经过加工后再使用时,可以使用getters加工。
src/store/index.js文件:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const actions = {
//加法不需要经过逻辑运算获取啥的。
}
const mutations = {
JIA(state,value){
console.log("mutations中的JIA被调用了")
state.sum += value
}
}
const state = {
sum:0//当前和
}
//准备getters,用于将state中的数据进行加工
const getters = {
bigSum(state){
return state.sum*10
}
}
const store = new Vuex.Store({
actions,
mutations,
state,
//不要忘记在store中配置
getters
})
export default store
Count.vue文件:
<template>
<div>
<h1>当前求和为:{{$store.state.sum}}</h1>
<h3>当前求和放大10倍后:{{$store.getters.bigSum}}</h3>
<select v-model="n">
<option :value="1">1</option>
<option :value="2">2</option>
<option :value="3">3</option>
</select>
<button @click="increment">+</button>
</div>
</template>
<script>
export default{
name:'Count',
data(){
return{
n:1,//用户选择的数字
}
},
methods:{
increment(){
this.$store.commit('JIA',this.n)
},
},
mounted(){
console.log(this.$store)
}
}
</script>
<style scoped>
button{
margin-left: 5px;
}
</style>
5.2 总结
6. Vuex中的 四个map方法
6.1 一些注意事项
键值对的一些注意事项:
mounted(){
/*
注意事项:
对象中键值对,key键的本身就是字符串,
就像下面的sum原型就是'sum',只不过精简了。
但是value值,必须指定好!没有精简!!
mapState只能操作state中的数据。像上面的bigSum是getters中的内容。
*/
const x = mapState({
he:'sum',
xuexiao:'school',
xueke:'subject'
})
console.log(x)
}
es6语法: …的作用。
6.2 Vuex中的 mapState
mapState就是映射状态,意思就是帮忙生成操作state的代码。一般应用到计算属性中。
效果就像下面的计算属性注释中的内容一样:
<template>
<div>
<h1>当前求和为:{{he}}</h1>
<h3>当前求和放大10倍后:{{bigSum}}</h3>
<h3>我在{{xuexiao}} ,学习{{xueke}}</h3>
<select v-model="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>
import {mapState} from 'vuex'
export default{
name:'Count',
data(){
return{
n:1,//用户选择的数字
}
},
computed:{
/*
靠自己写的计算属性
he(){
return this.$store.state.sum
},
xuexiao(){
return this.$store.state.school
},
xueke(){
return this.$store.state.subject
},
*/
//靠mapState生成的类似上面计算属性的效果:
//es6语法 ...相当于合并了mapState
//
...mapState({
he:'sum',
xuexiao:'school',
xueke:'subject'
}),
bigSum(){
return this.$store.getters.bigSum
},
},
methods:{
increment(){
this.$store.commit('JIA',this.n)
},
decrement(){
this.$store.commit('JIAN',this.n)
},
incrementOdd(){
this.$store.dispatch('jiaOdd',this.n)
},
incrementWait(){
this.$store.dispatch('jiaWait',this.n)
},
},
mounted(){
}
}
</script>
<style scoped>
button{
margin-left: 5px;
}
</style>
mapState有两种写法一种是对象写法,一种是数组写法:
- mapState对象写法:
//贴合上面内容,这里的键就是函数中的键,值就是this.$store.state.value的value值。
mapState({
he:'sum',
xuexiao:'school',
xueke:'subject'
})
- mapState数组写法:
computed:{
/*
靠自己写的计算属性:
当键名是sum , state对应的属性也是sum就可以用数组形式来描述。
sum(){
return this.$store.state.sum
},
school(){
return this.$store.state.school
},
subject(){
return this.$store.state.subject
},
*/
//如何修改的内容像上面的sum,school等都一样!!
//就可以用数组形式来写!
...mapState(['sum','school','subject']),
bigSum(){
return this.$store.getters.bigSum
},
},
6.2 Vuex中的 mapgetters
和mapState一样,mapState对应的是$store中的state状态;而mapGetters是对应的是$store的getters配置项中的内容。
// bigSum(){
// return this.$store.getters.bigSum
// },
// ...mapGetters(bigSum:'bigSum'), //对象写法
...mapGetters(['bigSum']) //数组写法
将mapState和mapGetters整合一起,就发现代码精简了不少。mapState和mapGetters就是用来精简代码的。
<template>
<div>
<h1>当前求和为:{{sum}}</h1>
<h3>当前求和放大10倍后:{{bigSum}}</h3>
<h3>我在{{school}} ,学习{{subject}}</h3>
<select v-model="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>
import {mapState,mapGetters} from 'vuex'
export default{
name:'Count',
data(){
return{
n:1,//用户选择的数字
}
},
computed:{
...mapState(['sum','school','subject']),
...mapGetters(['bigSum']) //数组写法
},
methods:{
increment(){
this.$store.commit('JIA',this.n)
},
decrement(){
this.$store.commit('JIAN',this.n)
},
incrementOdd(){
this.$store.dispatch('jiaOdd',this.n)
},
incrementWait(){
this.$store.dispatch('jiaWait',this.n)
},
},
mounted(){
}
}
</script>
<style scoped>
button{
margin-left: 5px;
}
</style>
6.3 MapActions 和 MapMutations
MapMutations,MapActions与上面两个Map方法操作一样的,作用也都一样,就是为了帮助我们生成函数,简化代码,简化操作。
MapMutations是生成对应的方法,方法中会调用commit方法,跳过actions直接联系mutations对象。
- MapMutations的对象写法:
methods:{
/*
//注意event事件对象!!!,需要我们在前面传递参数!!!
//如果不传递参数那么默认value值就是event对象了。
increment(value){
this.$store.commit('JIA',value)
},
decrement(value){
this.$store.commit('JIAN',value)
},
*/
//代码效果如上面代码,注意value不是我们的this.n了,而是一个事件!
...mapMutations({increment:'JIA',decrement:'JIAN'}),
},
- MapMutation的数组写法:
/*
JIA(value){
this.$store.commit('JIA',value)
},
JIAN(value){
this.$store.commit('JIAN',value)
},
*/
//mapMutations数组写法,一样数组写法就是要求二者相同!
...mapMutations(['JIA','JIAN'])
mapActions是生成对应的方法,方法中会调用dispatch方法,去联系actions对象。
- mapActions的对象写法:
methods:{
/*
incrementOdd(){
this.$store.dispatch('jiaOdd',this.n)
},
incrementWait(){
this.$store.dispatch('jiaWait',this.n)
},
*/
//对象形式写法
...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
}
- mapActions的数组写法:
methods:{
/*
jiaOdd(){
this.$store.dispatch('jiaOdd',this.n)
},
jiaWait(){
this.$store.dispatch('jiaWait',this.n)
},
*/
//数组形式写法
...mapActions(['jiaOdd','jiaWait'])
},
所有代码效果:
<template>
<div>
<h1>当前求和为:{{sum}}</h1>
<h3>当前求和放大10倍后:{{bigSum}}</h3>
<h3>我在{{school}} ,学习{{subject}}</h3>
<select v-model="n">
<option :value="1">1</option>
<option :value="2">2</option>
<option :value="3">3</option>
</select>
<button @click="JIA(n)">+</button>
<button @click="JIAN(n)">-</button>
<button @click="jiaOdd(n)">当前求和为奇数在加</button>
<button @click="jiaWait(n)">等一等在加</button>
</div>
</template>
<script>
import {mapState,mapGetters,mapMutations,mapActions} from 'vuex'
export default{
name:'Count',
data(){
return{
n:1,//用户选择的数字
}
},
computed:{
...mapState(['sum','school','subject']),
...mapGetters(['bigSum']) //数组写法
},
methods:{
...mapMutations(['JIA','JIAN']),
...mapActions(['jiaOdd','jiaWait'])
},
mounted(){
}
}
</script>
<style scoped>
button{
margin-left: 5px;
}
</style>
6.4 总结
四个map的作用就是为了简化代码,操作方法。让vue给我生成函数代码。
7. Vuex的模块化(namespaced)
7.1 Vuex的模块化
我们将不同的信息按照对象的形式,给他们分离出来,实现一个中模块化的效果。
src/store/index.js文件:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
//我们将不同相关的配置分别封装台不同的对象参数中。
//求和相关的配置
const conuntOptions = {
actions:{
jiaOdd(context,value){
console.log("actions中的jiaOdd被调用了")
if(context.state.sum % 2){
context.commit('JIAODD',value)
}
},
jiaWait(context,value){
console.log("actions中的jiaWait被调用了")
setTimeout(()=>{
context.commit('JIANWAIT',value)
},500)
}
},
mutations:{
JIA(state,value){
console.log("mutations中的JIA被调用了")
state.sum += value
},
JIAN(state,value){
console.log("mutations中的JIAN被调用了")
state.sum -= value
},
JIAODD(state,value){
console.log("mutations中的JIAODD被调用了")
state.sum += value
},
JIANWAIT(state,value){
console.log("mutations中的JIANWAIT被调用了")
state.sum += value
},
},
state:{
sum:0,//当前和
school:'清华大学',
subject:'java高级程序员',
},
getters:{
bigSum(state){
return state.sum*10
}
}
}
//人员管理相关的配置
const personOptions = {
actions:{},
mutations:{
ADD_PERSON(state,value){
console.log("mutations中的ADD_PERSON被调用了")
state.personList.unshift(value);
}
},
state:{
personList:[
{id:'001',name:'张三'}
]
},
gettes:{}
}
//使用modules这种模块化的效果实现起来更加方便
export default new Vuex.Store({
modules:{
countAbout:conuntOptions,
personAbout:personOptions
}
})
Count.vue文件:
<template>
<div>
<h1>当前求和为:{{countAbout.sum}}</h1>
<h3>我在{{countAbout.school}} ,学习{{countAbout.subject}}</h3>
<h3 style="color: red;">Person组件的总人数是{{personAbout.personList.length}}</h3>
<select v-model="n">
<option :value="1">1</option>
<option :value="2">2</option>
<option :value="3">3</option>
</select>
<button @click="JIA(n)">+</button>
<button @click="JIAN(n)">-</button>
<button @click="jiaOdd(n)">当前求和为奇数在加</button>
<button @click="jiaWait(n)">等一等在加</button>
</div>
</template>
<script>
import {mapState,mapGetters,mapMutations,mapActions} from 'vuex'
export default{
name:'Count',
data(){
return{
n:1,//用户选择的数字
}
},
computed:{
//这样我们直接通过countAbout和personAbout拿到数据。
...mapState(['countAbout','personAbout']),
...mapGetters(['bigSum']) //数组写法
},
methods:{
...mapMutations(['JIA','JIAN']),
...mapActions(['jiaOdd','jiaWait'])
},
}
</script>
<style scoped>
button{
margin-left: 5px;
}
</style>
7.2 针对map方法的 namespaced配置
当我们使用了模块化的使用,必须要给每一个模块对象配置namespaced设置为true,开启命名空间。
这样我们的map方法的第一个参数就可以指定哪一个模块下的state,mutations,actions,getters的情况。就更加的进一步简化代码了。
src/store/index.js文件:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
//我们将不同相关的配置分别封装台不同的对象参数中。
//求和相关的配置
const conuntOptions = {
//namespaced的默认值是false。true就是开启命名空间。
//一旦开始了命名空间,map方法就可以使用...mapState('countAbout',['sum','school','subject'])这样的形式来识别。
namespaced:true,
actions:{
jiaOdd(context,value){
console.log("actions中的jiaOdd被调用了")
if(context.state.sum % 2){
context.commit('JIAODD',value)
}
},
jiaWait(context,value){
console.log("actions中的jiaWait被调用了")
setTimeout(()=>{
context.commit('JIANWAIT',value)
},500)
}
},
mutations:{
JIA(state,value){
console.log("mutations中的JIA被调用了")
state.sum += value
},
JIAN(state,value){
console.log("mutations中的JIAN被调用了")
state.sum -= value
},
JIAODD(state,value){
console.log("mutations中的JIAODD被调用了")
state.sum += value
},
JIANWAIT(state,value){
console.log("mutations中的JIANWAIT被调用了")
state.sum += value
},
},
state:{
sum:0,//当前和
school:'清华大学',
subject:'java高级程序员',
},
getters:{
bigSum(state){
return state.sum*10
}
}
}
//人员管理相关的配置
const personOptions = {
namespaced:true,
actions:{},
mutations:{
ADD_PERSON(state,value){
console.log("mutations中的ADD_PERSON被调用了")
state.personList.unshift(value);
}
},
state:{
personList:[
{id:'001',name:'张三'}
]
},
gettes:{}
}
//使用modules这种模块化的效果实现起来更加方便
export default new Vuex.Store({
modules:{
countAbout:conuntOptions,
personAbout:personOptions
}
})
Count.vue文件:
<template>
<div>
<h1>当前求和为:{{sum}}</h1>
<h3>当前求和放大10倍后:{{bigSum}}</h3>
<h3>我在{{school}} ,学习{{subject}}</h3>
<h3 style="color: red;">Person组件的总人数是{{personList.length}}</h3>
<select v-model="n">
<option :value="1">1</option>
<option :value="2">2</option>
<option :value="3">3</option>
</select>
<button @click="increment(n)">+</button>
<button @click="decrement(n)">-</button>
<button @click="jiaOdd(n)">当前求和为奇数在加</button>
<button @click="jiaWait(n)">等一等在加</button>
</div>
</template>
<script>
import {mapState,mapGetters,mapMutations,mapActions} from 'vuex'
export default{
name:'Count',
data(){
return{
n:1,//用户选择的数字
}
},
computed:{
/*
这种写法,可以简化,让我们直接使用sum,school调用了!
总结起来就是两种写法:
'modules中的key值对象名' , ['map的数组形式的写法'] ;
'modules中的key值对象名' , {方法名:'map的对象形式写法'}
总结起来就是当我们使用了模块化的使用,必须要用namespaced设置为true,开启命名空间。
这样我们的map方法的第一个参数就可以指定哪一个模块下的state,mutations,actions,getters的情况。
*/
...mapState('countAbout',['sum','school','subject']),
...mapState('personAbout',['personList']),
...mapGetters('countAbout',['bigSum'])
},
methods:{
...mapMutations('countAbout',{increment:'JIA',decrement:'JIAN'}),
...mapActions('countAbout',['jiaOdd','jiaWait'])
},
}
</script>
<style scoped>
button{
margin-left: 5px;
}
</style>
7.3 对于不使用map方法 ,程序员自己commit,dispatch,如何找到对应的模块。
对于不是map方法的形式,直接commit方法或dispatch方法。
想要找到modules对应的actions或mutations就可以使用" / "来划分出来。
methods:{
add(){
//使用nanoid生成一个唯一的字符串
const personObj = {id:nanoid(),name:this.name}
/*
对于不是map方法的形式,直接commit方法或dispatch方法。
想要找到modules对应的actions或mutations就可以使用/来划分出来。
模块键名:方法名
*/
this.$store.commit('personAbout/ADD_PERSON',personObj)
this.name = ''
}
}
对于手动写的getters操作:
firstPersonName(){
console.log(this.$store)
//对象直接获取因为有个/ ,我们不能直接this.$store.getters.personAbout/firstPersonName这不行!
//但是对于对象我们可以换种形式,如下:
return this.$store.getters['personAbout/firstPersonName']
}
8. vuex模板化完整版案例
8.1 案例
目录结构:
index.js文件:
import Vue from 'vue'
import Vuex from 'vuex'
//我们只需要引入就可以了
import personOptions from './Person.js'
import conuntOptions from './Count.js'
Vue.use(Vuex)
export default new Vuex.Store({
modules:{
countAbout:conuntOptions,
personAbout:personOptions
}
})
Count.js文件(专门处理求和的模块)
//求和相关的配置
const conuntOptions = {
//namespaced的默认值是false。true就是开启命名空间。
//一旦开始了命名空间,map方法就可以使用...mapState('countAbout',['sum','school','subject'])这样的形式来识别。
namespaced:true,
actions:{
jiaOdd(context,value){
console.log("actions中的jiaOdd被调用了")
if(context.state.sum % 2){
context.commit('JIAODD',value)
}
},
jiaWait(context,value){
console.log("actions中的jiaWait被调用了")
setTimeout(()=>{
context.commit('JIANWAIT',value)
},500)
}
},
mutations:{
JIA(state,value){
console.log("mutations中的JIA被调用了")
state.sum += value
},
JIAN(state,value){
console.log("mutations中的JIAN被调用了")
state.sum -= value
},
JIAODD(state,value){
console.log("mutations中的JIAODD被调用了")
state.sum += value
},
JIANWAIT(state,value){
console.log("mutations中的JIANWAIT被调用了")
state.sum += value
},
},
state:{
sum:0,//当前和
school:'清华大学',
subject:'java高级程序员',
},
getters:{
bigSum(state){
return state.sum*10
}
}
}
export default conuntOptions
Person.js文件(专门处理person的模块)
import axios from "axios"
import {nanoid} from 'nanoid'
//人员管理相关的配置
const personOptions = {
namespaced:true,
actions:{
//这里的context是当前模块的context
addPersonWang(context,value){
if(value.name.indexOf('王') === 0){
context.commit('ADD_PERSON',value)
}else{
alert('只能添加姓王的姓名')
}
},
addPersonServer(context){
// https://api.uixsj.cn/hitokoto/get?type=social 返回语录接口
axios.get('https://api.uixsj.cn/hitokoto/get?type=social').then(
response => {
const obj = {id:nanoid(),name:response.data}
context.commit('ADD_PERSON',obj)
},
error => {
alert(error.message)
}
)
}
},
mutations:{
ADD_PERSON(state,value){
console.log("mutations中的ADD_PERSON被调用了")
state.personList.unshift(value);
}
},
state:{
personList:[
{id:'001',name:'张三'}
]
},
getters:{
//这里的state也是当前模块的state
firstPersonName(state){
return state.personList[0].name
}
}
}
export default personOptions
Count.vue文件:
<template>
<div>
<h1>当前求和为:{{sum}}</h1>
<h3>当前求和放大10倍后:{{bigSum}}</h3>
<h3>我在{{school}} ,学习{{subject}}</h3>
<h3 style="color: red;">Person组件的总人数是{{personList.length}}</h3>
<select v-model="n">
<option :value="1">1</option>
<option :value="2">2</option>
<option :value="3">3</option>
</select>
<button @click="increment(n)">+</button>
<button @click="decrement(n)">-</button>
<button @click="jiaOdd(n)">当前求和为奇数在加</button>
<button @click="jiaWait(n)">等一等在加</button>
</div>
</template>
<script>
import {mapState,mapGetters,mapMutations,mapActions} from 'vuex'
export default{
name:'Count',
data(){
return{
n:1,//用户选择的数字
}
},
computed:{
/*
这种写法,可以简化,让我们直接使用sum,school调用了!
总结起来就是两种写法:
'modules中的key值对象名' , ['map的数组形式的写法'] ;
'modules中的key值对象名' , {方法名:'map的对象形式写法'}
总结起来就是当我们使用了模块化的使用,必须要用namespaced设置为true,开启命名空间。
这样我们的map方法的第一个参数就可以指定哪一个模块下的state,mutations,actions,getters的情况。
*/
...mapState('countAbout',['sum','school','subject']),
...mapState('personAbout',['personList']),
...mapGetters('countAbout',['bigSum'])
},
methods:{
...mapMutations('countAbout',{increment:'JIA',decrement:'JIAN'}),
...mapActions('countAbout',['jiaOdd','jiaWait'])
},
}
</script>
<style scoped>
button{
margin-left: 5px;
}
</style>
Person.vue文件:
<template>
<div>
<h1>人员列表</h1>
<h3 style="color: red;">上方组件的求和为:{{sum}}</h3>
<h3>列表中第一个人的名字是:{{firstPersonName}}</h3>
<input type="text" placeholder="请输入名字" v-model="name">
<button @click="add">添加</button>
<button @click="addWang">添加一个姓王的人</button>
<button @click="addPersonServer">添加一个人,名字是一个语录</button>
<ul>
<li v-for="p in personList" :key="p.id">{{p.name}}</li>
</ul>
</div>
</template>
<script>
import {nanoid} from 'nanoid'
import {mapState} from 'vuex'
export default {
name:'Person',
data(){
return {
name:''
}
},
computed:{
personList(){
return this.$store.state.personAbout.personList
},
sum(){
return this.$store.state.countAbout.sum
},
firstPersonName(){
console.log(this.$store)
return this.$store.getters['personAbout/firstPersonName']
}
},
methods:{
add(){
const personObj = {id:nanoid(),name:this.name}
/*
对于不是map方法的形式,直接commit方法或dispatch方法。
想要找到modules对应的actions或mutations就可以使用/来划分出来。
*/
this.$store.commit('personAbout/ADD_PERSON',personObj)
this.name = ''
},
addWang(){
const personObj = {id:nanoid(),name:this.name}
this.$store.dispatch('personAbout/addPersonWang',personObj)
this.name = ''
},
addPersonServer(){
this.$store.dispatch('personAbout/addPersonServer')
}
}
}
</script>
<style>
</style>
8.2 总结
更多推荐
所有评论(0)