目录
- Vuex
- 1. 理解Vuex
- 1.1 组件之间共享数据的方式
- 1.2 Vuex是什么
- 1.2 什么时候使用Vuex
- 1.3 Vuex的工作原理图
- 2 使用Vuex
- 2.1 搭建Vuex环境
- 2.2 Vuex基本使用
- 2.2.1 State
- 2.2.2 Getters
- 2.2.3 Mutations
- 2.2.4 Actions
- 2.2.5 Modules 模块化+命名空间
- 3 求和案例
- 3.1 使用纯vue编写
- 3.2 使用Vuex编写
- 3.2.1 原始写法
- 3.2.2 用mapXXX优化后
- 3.2.2 多组件共享数据
- 3.2.3 模块化优化后
- 4 求和案例2
- 4.1 props传递值
- 4.2 Vuex的state传递
- 4.3 Matuations来修改状态
- 4.4 Mutations带参数传递修改状态
- 5 多组件共享数据案例
Vuex
1. 理解Vuex
1.1 组件之间共享数据的方式
父向子传值:v-bind
属性绑定
子向父传值:v-on
事件绑定
兄弟组件之间共享数据: EventBus(事件总线)
$on
接收数据的那个组件
$emit
发送数据的那个组件
1.2 Vuex是什么
1.概念: 专门在 Vue 中实现集中式状态(数据)管理的一个 Vue 插件,对 Vue 应用中多个组件的共享状态进行集中式的管理 (读/写),也是一种组件间信的方式,且适用于任意组件间通信。
Vuex Github: https://github.com/vuejs/vuex
- 全局事件总线和Vuex对比
1.2 什么时候使用Vuex
处理大量的需要在组件间传递的数据,直接定义一个全局的data属性保存就行了。
如果我们的页面比较简单,切记千万不要没事找事引入Vuex,我们使用Vuex是因为项目变得复杂之后,有很多数据需要在父组件、子组件和孙组件之间传递,处理起来很繁琐,于是就需要Vuex这样一个可以对这一部分数据进行统一管理的东西,也是响应式
什么情况需要使用Vuex管理状态在多个组件间共享?
- 多个组件依赖于同一状态
- 来自不同组件的行为需要变更同一状态
大型项目中组件很多,多个组件中共用的数据
例如:用户的登录状态、用户名称、头像、地理位置信息等
例如:商品的收藏、购物车中的物品。
例如:传递组件之间传递层次太多、不相关组件、公用组件
Vuex有点类似cookie和session,session是用于服务器端共享,cookie是用于浏览器的,Vuex是用于前端组件间共享
1.3 Vuex的工作原理图
四个核心概念
Vuex 的四个核心概念分别是:
- The state tree:Vuex 使用单一状态树,用一个对象就包含了全部的应用层级状态。至此它便作为一个『唯一数据源(SSOT)』而存在。这也意味着,每个应用将仅仅包含一个 store 实例。单状态树让我们能够直接地定位任一特定的状态片段,在调试的过程中也能轻易地取得整个当前应用状态的快照。
- Getters:用来从 store 获取 Vue 组件数据。
- Mutation:事件处理器用来驱动状态的变化。
- Actions:可以给组件使用的函数,以此用来驱动事件处理器 mutations
Vuex和简单的全局对象是不同的,当Vuex从store中读取状态值的时候,若状态发生了变化,那么相应的组件也会高效的更新。并且,改变store中状态的唯一途径就是提交commit mutations。这样便于我们跟踪每一次状态的变化。只要发生了状态的变化,一定伴随着mutation的提交。
2 使用Vuex
2.1 搭建Vuex环境
- 下载安装 Vuex
npm i vuex@3
npm i vuex
是安装最新版本的Vuex
注意:
- Vue2中,要用Vuex的3版本
- Vue3中,要用Vuex的4版本
- 创建
src/store/index.js
该文件用于创建Vuex中最为核心的store
文件目录
store/index.js
写法一:
import Vue from 'vue'
import Vuex from 'vuex' //引入VuexVue.use(Vuex) //应用Vuex//创建并暴露store
export default new Vuex.Store({//数据,相当于datastate: {},getters: {}, //里面定义方法,操作state方法mutations: {}, // 操作数据Stateactions: {}, //用于响应组件中的动作modules: {},
})
写法二:
import Vue from 'vue'
import Vuex from 'vuex' //引入VuexVue.use(Vuex) //应用Vuexconst actions = {} //用于响应组件中的动作const mutations = {} // 操作数据Stateconst state = {}const getters= {} //里面定义方法,操作state方法const modules1 = {}const modules2 = {}//创建并暴露store
export default new Vuex.Store({//数据,相当于datastate,getters, mutations, actions, modules: {modules1,modules2}
})
- 在
src/main.js
中创建vm
中传入store
配置项
2.2 Vuex基本使用
Vuex的基本使用
Vuex中一共有五个状态 State、Getter、Mutation、Action、Module
2.2.1 State
提供唯一的公共数据源,所有共享的数据统一放到store的state进行储存,相似与data
在vuex中state中定义数据,可以在任何组件中进行调用
import Vue from 'vue'
import Vuex from 'vuex'Vue.use(Vuex)export default new Vuex.Store({//数据,相当于datastate: {name:"张三",age:12,sex: '男',count:0},
})
读取
方法一:在标签中直接使用
<p>{{ $store.state.name }}</p>
<p>{{ $store.state.age}}</p>
方法二:
this.$store.state.全局数据名称
方法三:
从vuex中按需导入mapstate函数
// 1. 从 vuex 中按需导入 mapState 函数
import { mapState } from "vuex";
通过刚才导入的 mapState 函数,将当前组件需要的全局数据,映射为当前组件的 computed 计算属性:
// 2. 将全局数据,映射为当前组件的计算属性
computed: { // 对象写法...mapState({name:'name', age:'age', sex:'sex'}) // 数组写法...mapState(['name', 'age', 'sex'])
}
修改Vuex中的数据
$store.dispatch('action中的方法名',数据)
//或是
$store.commit('mutations中的方法名',数据)
若没有网络请求或其他业务逻辑,组件中也可越过 actions
,即不写 dispatch
,直接编
写commit
2.2.2 Getters
Getters 用于对 Store 中的数据进行加工处理形成新的数据。
①Getters 可以对 Store 中已有的数据加工处理之后形成新的数据,类似 Vue 的计算属性。
②Store 中数据发生变化,Getters 的数据也会跟着变化。
具体操作类似于前几种
在Vuex中定义:
// 定义 Getters
export default new Vuex.Store({state: {count: 0},getters: {showNum: state => {return '当前最新的数量是【'+ state.count * 10 +'】'}}
})
在组件中使用:
方法一:在标签中直接使用
<p>{{ $store.getter.name }}</p>
<p>{{ $store.state.age}}</p>
方法二:
this.$store.getters.名称
方法二:
从vuex中按需导入mapGetters 函数
import { mapGetters } from 'vuex'
通过刚才导入的 mapGetters 函数,用于帮助映射 getters
中的数据为当前组件的 computed 计算属性:
computed: {//对象写法...mapGetters({showNum:'showNum'})//数组写法...mapGetters(['showNum'])
}
2.2.3 Mutations
Mutations 用于变更 Store中 的数据。
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:
每个 mutation 都有一个字符串的事件类型 (type)和一个回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数:
① 只能通过 mutations 变更 Store 数据,不可以直接操作 Store 中的数据。
② 通过这种方式虽然操作起来稍微繁琐一些,但是可以集中监控所有数据的变化。
在Vuex中定义
export default new Vuex.Store({//数据,相当于datastate: {name:"张三",age:12,sex: '男',count:0},mutations: {addCount(state, num) {state.count += num},reduce(state){state.count--}}
})
在组件中使用:
方法一:使用commit触发Mutations操作
// 触发mutations
methods: { btn() { // 触发 mutations 的第一种方式 this.$store.commit('addCount', 10) //每次加十} btn2() { // 触发 mutations 的第一种方式 this.$store.commit('reduce') }
}
方法二:使用辅助函数进行操作,具体方法同上
从vuex中按需导入mapMutations 函数
// 1. 从 vuex 中按需导入 mapMutations 函数
import { mapMutations } from 'vuex'
通过刚才导入的 mapMutations 函数,将需要的 mutations 函数,映射为当前组件的 methods 方法:
// 2. 将指定的 mutations 函数,映射为当前组件的 methods 函数
methods: {// 触发 mutations 的第二种方式 对象写法...mapMutations({addCount: 'addCount', reduce:'reduce'}),//或是// 触发 mutations 的第二种方式 数组写法...mapMutations(['addCount', 'reduce']),btn() { this.addCount(10) //每次加十} btn2() { this.reduce() }
}
2.2.4 Actions
Actions 用于处理异步任务。
如果通过异步操作变更数据,必须通过 Actions,而不能使用 Mutation,但是在 Actions 中还是要通过触发Mutation 的方式间接变更数据。
在Vuex中定义:
讲上面的操作改为异步操作
// 定义 Actions
export default new Vuex.Store({ // ...省略其他代码 mutations: { //第一个参数是state,第二参数是传的参数addCount(state, num) { //state中的数据的改变会触发页面上对应数据的改变state.count += num},reduce(state){state.count--}}, // 异步操作actions: { asynReduce(context) { setTimeout(() => { context.commit('reduce') }, 1000) },//触发 actions 异步任务时携带参数,第一个参数是上下文对象,第二参数是传的参数asynAdd(context, num) { setTimeout(() => { //会找到mutation对应的方法context.commit('addCount', num) }, 1000) } }
})
在组件中使用:
方法一:直接使用 dispatch触发Action函数
methods: {btn() { // 触发 actions 的第一种方式this.$store.dispatch("asynAdd", 10)} btn2() { // 触发 actions 的第一种方式this.$store.dispatch("asynReduce")}
}
方法二:使用辅助函数
从vuex中按需导入mapActions 函数
// 1. 从 vuex 中按需导入 mapActions 函数
import { mapActions } from 'vuex'
通过刚才导入的 mapActions 函数,将需要的 actions 函数,映射为当前组件的 methods 方法:
// 2. 将指定的 actions 函数,映射为当前组件的 methods 函数
methods: { //对象写法...mapActions({asynAdd:'asynAdd', asynReduce:'asynReduce'}),//或是//数组写法...mapActions(['asynAdd', 'asynReduce']),btn() { this.asynAdd(10) //每次加十} btn2() { this.asynReduce() }
}
2.2.5 Modules 模块化+命名空间
-
目的:让代码更好维护,让多种数据分类更加明确
-
场景:当遇见大型项目时,数据量大,store就会显得很臃肿
为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割: -
基本写法
写法一:
const countAbout = {namespaced: true,state: {sum: 0,name: 'zhangsan',sex: 'man',},mutations: {...},actions: {...},getters: {bisSum(state){ return state.sum * 10}
}const personAbout= {namespaced: true,state: {personList: [{id: '0001',name: 'Lisi'}]},mutations: {...},actions: {...},getters: { ... }
}const store = new Vuex.Store({modules: {countAbout,personAbout}
})
写法二:
const store = new Vuex.Store({modules: {countAbout:{namespaced: true,state: { ... },mutations: {...},actions: {...},getters: { ... }},personAbout: {namespaced: true,state: { ... },mutations: {...},actions: {...},getters: { ... }}}
})
默认情况下,模块内部的 action 和 mutation 仍然是注册在全局命名空间的——这样使得多个模块能够对同一个 action 或 mutation 作出响应。
如果希望你的模块具有更高的封装度和复用性,你可以通过添加 namespaced: true
的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。
- 开启命名空间后,组件中读取
state
数据
//方法一:自己读取
this.$store.state.countAbout.sum
//方法二:借助mapState读取
...mapState('countAbout', ['sum', 'name', 'sex'])
- 开启命名空间后,组件中读取
getters
数据
//方法一:自己读取
this.$store.getters['personAbout/firstPersonName']
//方法二:借助mapGetters读取
...mapGetters('countAbout', ['bisSum'])
- 开启命名空间后,组件中调用
commit
//方法一:自己commit
this.$store.commit('personAbout/addPerson', person)
//方法二:借助mapMutations读取
...mapMutations('countAbout',{increment: 'add', decrement: 'reduce'})
- 开启命名空间后,组件中调用
dispatch
//方法一:自己commit
this.$store.dispatch('personAbout/addPersonWang', person)
//方法二:借助mapMutations读取
...mapActions('countAbout',{incrementOdd:'asyncAddOdd', incrementWait:'asyncAddWait'})
3 求和案例
3.1 使用纯vue编写
App.vue
<template><div class="container"><Count/></div>
</template><script>
import Countfrom './components/Count'
export default {name: 'App',components: {Count}
}
</script>
<style></style>
Count.vue
<template><div class="hello"><h1>当前求和为:{{sum}}</h1><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>
<style scoped></style>
3.2 使用Vuex编写
3.2.1 原始写法
src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex' //引入VuexVue.use(Vuex) //应用Vuex//创建并暴露store
export default new Vuex.Store({//数据,相当于datastate: {sum: 0,name: 'zhangsan',sex: 'man'},getters: {}, //里面定义方法,操作state方法mutations: {add(state, num) {state.sum += num},reduce(state){state.sum--}}, // 操作异步操作mutationactions: {asyncAddWait(context, num){setTimeout(()=>{context.commit('add', num)},500)},asyncAddOdd(context, num){if(context.state.sum % 2){context.commit('add', num)}}}, //用于响应组件中的动作modules: {},
})
Count.vue
<template><div class="hello"><h1>当前求和为:{{$store.state.sum}}</h1><h3>当前求和放大10倍:{{$store.getters.bigSum}}</h3><h3>姓名:{{ $store.statename }},性别: {{ $store.statesex }}</h3><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: {//使用mutaionincrement() {this.$store.commit('add', this.n)},decrement() { this.$store.commit('reduce')},//使用Actions异步incrementOdd() {this.$store.dispatch('asyncAddOdd', this.n)},incrementWait() {this.$store.dispatch('asyncAddWait', this.n)}}
}
</script>
<style scoped></style>
3.2.2 用mapXXX优化后
Count.vue
<template><div class="hello"><h1>当前求和为:{{ sum }}</h1><h3>当前求和放大10倍:{{bigSum}}</h3><h3>姓名:{{ name }},性别: {{ sex }}</h3><select v-model.number="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="incrementOdd(n)">当前求和为奇数再加</button><button @click="incrementWait(n)">等一等再加</button></div>
</template><script>
import {mapState,mapGetters,mapMutations, mapActions} from 'vuex'
export default {name: 'Count',data() {return {n: 1}},computed: {//借助mapSate和mapGetters生成计算属性...mapState(['sum','name','sex']),...mapGetters(['bigSum'])},methods: {...mapMutations({increment: 'add', decrement: 'reduce'}),...mapActions({incrementOdd:'asyncAddOdd', incrementWait:'asyncAddWait'})//使用mutaion//increment() {this.$store.commit('add', this.n)},//decrement() { this.$store.commit('reduce')},//使用Actions异步//incrementOdd() {this.$store.dispatch('asyncAddOdd', this.n)},//incrementWait() {this.$store.dispatch('asyncAddWait', this.n)}}
}
</script>
<style scoped></style>
3.2.2 多组件共享数据
src/App.vue
<template><div class="container"><Count/><Person/></div>
</template><script>
import Count from './components/Count'
import Person from './components/Person'
export default {name: 'App',components: {Count,Person}
}
</script>
<style></style>
src/components/Count.vue
<template><div class="hello"><h1>当前求和为:{{ sum }}</h1><h3>当前求和放大10倍:{{bigSum}}</h3><h3>姓名:{{ name }},性别: {{ sex }}</h3><h3 style="color:red">Person组件的总人数是: {{ personList.length }}</h3><select v-model.number="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="incrementOdd(n)">当前求和为奇数再加</button><button @click="incrementWait(n)">等一等再加</button></div>
</template><script>
import {mapState,mapGetters,mapMutations, mapActions} from 'vuex'
export default {name: 'Count',data() {return {n: 1}},computed: {//借助mapSate和mapGetters生成计算属性...mapState(['sum','name','sex','personList']),...mapGetters(['bigSum'])},methods: {...mapMutations({increment: 'add', decrement: 'reduce'}),...mapActions({incrementOdd:'asyncAddOdd', incrementWait:'asyncAddWait'})}
}
</script>
<style scoped></style>
src/components/Person.vue
<template><div><hr><h1>人员列表</h1><h3 style="color:red">Count组件求和为: {{ sum }}</h3><input type="text" placeholder="请输入" v-model="name"><button @click="add">添加</button><br><br><ul><li v-for="p in personList" :key="p.id">{{p.name}}</li></ul></div>
</template><script>
import {mapState} from 'vuex'
import {nanoid} from 'nanoid'
export default {name: 'Person',components: {},props: {},data() {return {name: ''};},computed:{...mapState(['personList', 'sum'])},methods: {add() {if(this.name === '') return const personObj = {id: nanoid(), name: this.name}this.$store.commit('addPerson', personObj)this.name = ''}}
};
</script>
<style scoped></style>
src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex' //引入VuexVue.use(Vuex) //应用Vuex//创建并暴露store
export default new Vuex.Store({//数据,相当于datastate: {sum: 0,name: 'zhangsan',sex: 'man',personList: [{id: '0001',name: 'Lisi'}]},//里面定义方法,操作state方法getters: {bigSum: state=>{return state.sum * 10}}, // 操作异步操作mutation mutations: {add(state, num) {state.sum += num},reduce(state){state.sum--},addPerson(state, value) {state.personList.unshift(value)}}, //用于响应组件中的动作 actions: {asyncAddWait(context, num){setTimeout(()=>{context.commit('add', num)},500)},asyncAddOdd(context, num){if(context.state.sum % 2){context.commit('add', num)}}},
})
3.2.3 模块化优化后
src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex' //引入Vuex
import countOptions from './count'
import personOptions from './person'
import count from './count'
Vue.use(Vuex) //应用Vuex//创建并暴露store
export default new Vuex.Store({modules: {countAbout: countOptions,personAbout: personOptions},
})
src/store/count.js
export default {namespaced: true,state: {sum: 0,name: 'zhangsan',sex: 'man',},getters: {bigSum(state){return state.sum * 10}},mutations: {add(state, num) {state.sum += num},reduce(state){state.sum--},},actions: {asyncAddWait(context, num){setTimeout(()=>{context.commit('add', num)},500)},asyncAddOdd(context, num){if(context.state.sum % 2){context.commit('add', num)}}}
}
src/store/person.js
import axios from "axios"
import { nanoid } from 'nanoid'export default {namespaced: true,state: {personList: [{id: '0001',name: 'Lisi'}]},getters: {firstPersonName(state) {return state.personList[0].name}},mutations: {addPerson(state, value) {state.personList.unshift(value)}},actions: {addPersonWang(context, value) {if(value.name.indexOf('王') === 0){context.commit('addPerson', value)}else {alert('添加的人必须为王')}},addPersonServer(context) {axios.get('http://api.uixsj.cn/hitokoto/get?type=social').then(response => {context.commit('addPerson', {id: nanoid(), name:response.data})},error => {alert(error.message)})}}
}
Count和Person的呈现了两种不同的写法,一个是用mapXXX的写法,一个是直接使用this.$store的写法
src/components/Count.vue
<template><div class="hello"><h1>当前求和为:{{ sum }}</h1><h3>当前求和放大10倍:{{bigSum}}</h3><h3>姓名:{{ name }},性别: {{ sex }}</h3><h3 style="color:red">Person组件的总人数是: {{ personList.length }}</h3><select v-model.number="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="incrementOdd(n)">当前求和为奇数再加</button><button @click="incrementWait(n)">等一等再加</button></div>
</template><script>
import {mapState,mapGetters,mapMutations, mapActions} from 'vuex'
export default {name: 'Count',data() {return {n: 1}},computed: {//借助mapSate和mapGetters生成计算属性...mapState('countAbout',['sum','name','sex']),...mapState('personAbout', ['personList']),...mapGetters('countAbout',['bigSum'])},methods: {...mapMutations('countAbout',{increment: 'add', decrement: 'reduce'}),...mapActions('countAbout',{incrementOdd:'asyncAddOdd', incrementWait:'asyncAddWait'})}
}
</script>
<style scoped></style>
src/components/Person.vue
<template><div><hr><h1>人员列表</h1><h3 style="color:red">Count组件求和为: {{ sum }}</h3><h3>列表中第一个人的名字是: {{ firstPersonName }}</h3><input type="text" placeholder="请输入" v-model="name"><button @click="add">添加</button><button @click="addWang">添加一个姓王的人</button><button @click="addRandom">随机添加一个人</button><br><br><ul><li v-for="p in personList" :key="p.id">{{p.name}}</li></ul></div>
</template><script>
import {mapState, mapGetters,mapMutations,mapActions} from 'vuex'
import {nanoid} from 'nanoid'
export default {name: 'Person',components: {},props: {},data() {return {name: ''};},computed:{//直接读取的方法personList() { return this.$store.state.personAbout.personList },sum() { return this.$store.state.countAbout.sum },firstPersonName() { return this.$store.getters['personAbout/firstPersonName'] }},methods: {add() {if(this.name === '') return const personObj = {id: nanoid(), name: this.name}this.$store.commit('personAbout/addPerson', personObj)this.name = ''},addWang() {if(this.name === '') return const personObj = {id: nanoid(), name: this.name}this.$store.dispatch('personAbout/addPersonWang', personObj)this.name = ''},addRandom() {this.$store.dispatch('personAbout/addPersonServer')}}
};
</script>
<style scoped>
</style>
4 求和案例2
4.1 props传递值
helloword子组件使用Home组件声明的变量,可采用之前学习的组件传递值的方法
Home
组件
<template><div class="home"><h2>这是在单页模板中应用</h2><h3>{{count}}</h3><button @click="count--">-</button><button @click="count++">+</button><!-- 传递count给子组件helloword---><HelloWorld :count="count" msg="Welcome to Your Vue.js App"/></div>
</template><script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'
export default {name: 'Home',components: {HelloWorld},data() {return {count: 0}}
}
</script>
helloword
子组件
<template><div class="hello"><h1>{{ msg }}</h1><h3>在子组件hellword中应用Home中的Data</h3><h3>{{count}}</h3></div>
</template><script>
export default {name: 'HelloWorld',props: {count: Number}
}
</script><!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
……
</style>
效果
若About组件想要使用Home组件的count,通过组件传递的方式也可实现,就是有点麻烦,需要传递给中介App组件,App组件再传递给About组件。
4.2 Vuex的state传递
因此,在这里可采用Vuex,其配置文件在/store/index.js
import { createStore } from 'vuex'export default createStore({state: {//任何地方都可使用这个状态管理num: 0},mutations: { },actions: {},modules: {}
})
Home.vue
<template><div class="home"><h2>使用全局的状态管理</h2><h3>{{$store.state.num}}</h3><button @click="$store.state.num--">-</button><button @click="$store.state.num++">+</button></div>
</template><script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'export default {name: 'Home',components: {HelloWorld},
}
</script>
About.vue
<template><div class="about"><h1>This is an about page</h1><h3>{{$store.state.num}}</h3></div>
</template>
效果
4.3 Matuations来修改状态
Vuex最好采用Matuations来修改状态,而不是通过组件的形式
index.js
import { createStore } from 'vuex'export default createStore({state: {//任何地方都可使用这个状态管理num: 0,mnum: 0},mutations: {//自动把state的参数传过来sub(state) {state.mnum--;},add(state) {state.mnum++;}},actions: { },modules: {}
})
Home.vue
<template><div class="home"><h2>这是在单页模板中应用</h2><h3>{{count}}</h3><button @click="count--">-</button><button @click="count++">+</button><HelloWorld :count="count" msg="Welcome to Your Vue.js App"/><hr><h2>使用全局的状态管理</h2><h3>{{$store.state.num}}</h3><button @click="$store.state.num--">-</button><button @click="$store.state.num++">+</button><hr><h2>使用Mutations来修改状态</h2><h3>MNum:{{$store.state.mnum}}</h3><button @click="sub1()">-</button><button @click="add1()">+</button></div>
</template><script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'export default {name: 'Home',components: {HelloWorld},data() {return {count: 0}},methods: {add1() {this.$store.commit('add')},sub1() {this.$store.commit('sub')},}
}
</script>
About.vue
<template><div class="about"><h1>This is an about page</h1><h3>Num:{{$store.state.num}}</h3><h3>MNum:{{$store.state.mnum}}</h3></div>
</template>
效果
4.4 Mutations带参数传递修改状态
index.js
import { createStore } from 'vuex'export default createStore({state: {//任何地方都可使用这个状态管理num: 0,mnum: 0},mutations: {//自动把state的参数传过来sub(state) {state.mnum--;},add(state) {state.mnum++;},//接收一个参数sub2(state,count) {console.log(count);state.mnum-=count;},add2(state,count) {console.log(count);state.mnum+=count;},//接收多个参数sub3(state,payload) {console.log(payload);state.mnum-=(payload.count+payload.num);},add3(state,payload) {console.log(payload);state.mnum+=(payload.count+payload.num);}},actions: {},modules: {}
})
Home.vue
<template><div class="home"><hr><h2>使用Mutations来修改状态</h2><h3>MNum:{{$store.state.mnum}}</h3><button @click="sub1()">-</button><button @click="add1()">+</button><hr><h2>使用Mutations来修改状态带一个参数</h2><h3>MNum:{{$store.state.mnum}}</h3><button @click="sub2()">-</button><button @click="add2()">+</button><hr><h2>使用Mutations来修改状态带多个参数</h2><h3>MNum:{{$store.state.mnum}}</h3><button @click="sub3()">-</button><button @click="add3()">+</button></div>
</template><script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'export default {name: 'Home',components: {HelloWorld},data() {return {count: 0}},methods: {add1() {this.$store.commit('add')},sub1() {this.$store.commit('sub')},add2() {let count = 2;this.$store.commit('add2',count)},sub2() {let count = 2;this.$store.commit('sub2',count)},add3() {let payload = {count:2, num:1}this.$store.commit('add3',payload)},sub3() {let payload = {count:2, num:1}this.$store.commit('sub3',payload)//等价于//this.$store.commit({type:'sub3', payload})}}
}
</script>
效果