在单页面组件的开发中 Vue的vuex 都统称为同一状态管理,简单的理解就是你在state中定义了一个数据之后,你可以在所在项目中的任何一个组件里进行获取、进行修改,并且你的修改可以得到全局的响应变更
首先要安装、使用 vuex
首先在 vue 2.0+ 你的vue-cli项目中安装 vuex :
npm install vuex
接下来,在 main.js里面引入store,然后再全局注入一下,这样一来就可以在任何一个组件里面使用this.$store了:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
showFooter: true,
changableNum:0
},
mutations: {
},
actions: {
},
modules: {
}
})
store文件的index.js里面,
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
showFooter: true,
changableNum:0
},
mutations: {
},
actions: {
},
})
现在已经可以用this.或store.state.changebleNum在任何一个组件里面获取showfooter和changebleNum定义的值了,
created() {
console.log(this.$store.state.showFooter)
}
但这不是理想的获取方式;vuex官方API提供了一个getters,和vue计算属性computed一样,来实时监听state值的变化(最新状态),并把它也仍进Vuex.Store里面
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
showFooter: true,
changableNum:0
},
getters:{
isShow(state) {
return state.showFooter
},
getChangedNum(state){
return state.changableNum
}
},
mutations: {
},
actions: {
},
})
mutattions用于改变当前的状态,mutattions也是一个对象,这个对象里面可以放改变state的初始值的方法,具体的用法就是给里面的方法传入参数state或额外的参数,然后利用vue的双向数据驱动进行值的改变,同样的定义好之后也把这个mutations扔进Vuex.Store里面
mport Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
showFooter: true,
changableNum:0
},
getters:{
isShow(state) {
return state.showFooter
},
getChangedNum(state){
return state.changableNum
}
},
mutations: {
show(state) {
state.showFooter = true;
},
hide(state) { //同上
state.showFooter = false;
},
newNum(state,sum){
state.changableNum+=sum;
}
},
actions: {
},
})
时候你完全可以用 this.或store.commit('hide') 以及 this.$store.commit('newNum',6) 在别的组件里面进行改变showfooter和changebleNum的值了
//组件
mounted() {
this.$store.commit('newNum', 100)
}
// vuex
export default new Vuex.Store({
state: {
showFooter: true,
changableNum:0
},
getters:{
isShow(state) {
return state.showFooter
},
getChangedNum(state){
return state.changableNum
}
},
mutations: {
show(state) {
state.showFooter = true;
},
hide(state) { //同上
state.showFooter = false;
},
newNum(state,sum){
console.log(sum)
state.changableNum+=sum;
}
},
actions: {
},
})
但这不是理想的改变值的方式;因为在 Vuex 中,mutations里面的方法 都是同步事务,意思就是说:比如这里的一个this.$store.commit('newNum',sum)方法,两个组件里用执行得到的值,每次都是一样的,这样肯定不是理想的需求
好在vuex官方API还提供了一个actions,这个actions也是个对象变量,最大的作用就是里面的Action方法 可以包含任意异步操作,这里面的方法是用来异步触发mutations里面的方法,actions里面自定义的函数接收一个context参数和要变化的形参,context与store实例具有相同的方法和属性,所以它可以执行context.commit(' '),然后也不要忘了把它也扔进Vuex.Store里面:
export default new Vuex.Store({
state: {
showFooter: true,
changableNum:0
},
getters:{
isShow(state) {
return state.showFooter
},
getChangedNum(state){
return state.changableNum
}
},
mutations: {
show(state) {
state.showFooter = true;
},
hide(state) { //同上
state.showFooter = false;
},
newNum(state,sum){
state.changableNum+=sum;
}
},
actions: {
hideFooter(context) {
context.commit('hide');
},
showFooter(context) {
context.commit('show');
},
getNewNum(context,num){
context.commit('newNum',num)
}
},
})
而在外部组件里进行全局执行actions里面方法的时候,你只需要用执行
this.$store.dispatch('hideFooter')
或this.$store.dispatch('showFooter')
以及this.$store.dispatch('getNewNum',6)
这样就可以全局改变改变showfooter或changebleNum的值了,
页面a
<template>
<div class="home">
<img alt="Vue logo" src="../assets/logo.png">
<button @click="setStore(true)">你为什么没有女朋友</button>
<button @click="setStore(false)">我为什么有女朋友</button>
</div>
</template>
<script>
// @ is an alias to /src
export default {
name: 'Home',
methods:{
setStore(type){
type ? this.$store.dispatch('hideFooter') : this.$store.dispatch('showFooter')
}
},
created() {
},
mounted() {
}
}
</script>
// 页面b
<template>
<div class="about">
<p>{{isShow ? '因为我帅' : '因为你丑'}}</p>
</div>
</template>
<script>
export default {
computed:{
isShow(){
return this.$store.getters.isShow;
}
},
}
</script>
modules 模块化 以及 组件中引入 mapGetters、mapActions 和 mapStates的使用
因为在大多数的项目中,我们对于全局状态的管理并不仅仅一种情况的需求,有时有多方面的需求,比如写一个商城项目,你所用到的全局state可能是关于购物车这一块儿的也有可能是关于商品价格这一块儿的;像这样的情况我们就要考虑使用vuex中的 modules 模块化了,
//index.js
import Vue from 'vue'
import Vuex from 'vuex'
import obj from "./obj";
Vue.use(Vuex)
export default new Vuex.Store({
modules: {
obj
}
})
// obj.js
export default {
namespaced:true,//用于在全局引用此文件里的方法时标识这一个的文件名
state: {
showFooter: true,
changableNum: 0
},
getters: {
isShow(state) {
return state.showFooter
},
getChangedNum(state) {
return state.changableNum
}
},
mutations: {
show(state) {
state.showFooter = true;
},
hide(state) { //同上
state.showFooter = false;
},
newNum(state, sum) {
state.changableNum += sum;
}
},
actions: {
hideFooter(context) {
context.commit('hide');
},
showFooter(context) {
context.commit('show');
},
getNewNum(context, num) {
context.commit('newNum', num)
}
}
}
相应的js,其中的 namespaced:true 表示当你需要在别的文件里面使用( mapGetters、mapActions 接下来会说 )时,里面的方法需要注明来自哪一个模块的方法:
这样一改就有了至少一个模块的state管理文件了,现在你要运行当前的代码话,项目会报错!因为我们把上面的代码模块化分开了,引用的地方还没有改。接下来是 mapState,mapGetters,mapActions的使用,首先 在需要用的 组件里面先导入 import {mapState,mapGetters,mapActions} from 'vuex'
// about.vue
<template>
<div class="about">
<p>{{isShow ? '因为我帅' : '因为你丑'}}</p>
</div>
</template>
<script>
import {mapState} from 'vuex'; //先要引入
export default {
computed:{
...mapState({ //这里的...是超引用,ES6的语法,意思是state里有多少属性值我可以在这里放多少属性值
isShow:state=>state.obj.showFooter //注意这些与上面的区别就是state.obj,
//里面定义的obj是指obj.js里state的showFooter
}),
//你也可以用下面的mapGetters来获取isShow的值,貌似下面的更简洁
/*...mapGetters('obj',{ //obj指的是modules文件夹下的footerStatus.js模块
isShow:'isShow' //第一个isShow是我自定义的只要对应template里就行,
//第二个isShow是对应的obj.js里的getters里的isShow
})*/
},
}
</script>
// home.vue
<template>
<div class="home">
<img alt="Vue logo" src="../assets/logo.png">
<button @click="setStore(true)">你为什么没有女朋友</button>
<button @click="setStore(false)">我为什么有女朋友</button>
</div>
</template>
<script>
// @ is an alias to /src
export default {
name: 'Home',
components: {
},
methods:{
setStore(type){
type ? this.$store.dispatch('obj/hideFooter') : this.$store.dispatch('obj/showFooter')
}
},
created() {
},
mounted() {
}
}
</script>
目代码应该就不会报错了,好,最后咱们再来看一下mapActions的用法,实际上上面的this.$store.dispatch('footerStatus/showFooter')已经算是一种执行相应模块的action里的方法了,但有时会牵扯的事件的触发及传值,那就会有下面的mapActions用法了
home.vue
<template>
<div class="home">
<img alt="Vue logo" src="../assets/logo.png">
<button @click="add()">累加</button>
</div>
</template>
<script>
// @ is an alias to /src
import {mapActions} from 'vuex'
export default {
name: 'Home',
components: {
},
methods:{
...mapActions('obj',[ //obj是指modules文件夹下的obj.js
'getNewNum' //obj.js文件中的actions里的方法,在上面的@click中执行并传入实参
]),
add(){
this.getNewNum(1)
}
},
created() {
},
mounted() {
}
}
</script>
about
<template>
<div class="about">
{{arrList}}
</div>
</template>
<script>
import { mapGetters} from 'vuex'; //先要引入
export default {
computed:{
...mapGetters('obj',{ //用mapGetters来获取obj.js里面的getters
arrList:'getChangedNum'
})
},
}
</script>