Vuex

Vuex

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式

讲解基于 /F:\IntelliJ IDEA工作空间(vue)/vuex目录下的vuex

一、state:

相当于组件中的data,用来存放全局的数据

在store中定义数据,在组件中直接使用。

目录: store/index.js

<script>
  export default new Vuex.Store({
  //state相当于组件中的data,专门用来存放全局的数据
  state: {
    nums: "0" //这里定义一个全局数据nums
  },
  getters: {
  },
  mutations: {
  },
  actions: {
  },
  modules: {
  }
})
</script>

方法一:直接通过this.$store.state.nums获得全局数据nums,目录: Home.vue

<template>
  <div class="home">
      //直接通过 this.$store.state.nums取得数据
     <h1>Home页面的数字:{{this.$store.state.nums}}</h1>
  </div>
</template>

<script>
export default {
  name: 'Home'
}
</script>

方法二:通过computed计算属性获得全局数据nums,但是本质还是方法一。目录: ``

<template>
    <div>
        计算属性得到的数字:{{nums}}
    </div>
</template>

<script>
    export default {
        name: "NumComputed",
        computed: {
            nums() {
                return this.$store.state.nums //相当于还是调用方法一
            }
        }
    }
</script>

二、getters:

相当于组件中的computed,getter是全局的,computed是组件内部使用的。

export default new Vuex.Store({
  //state相当于组建中的data,专门用来存放全局的数据
  state: {
    nums: "0"
  },
  // getters相当于组件中的computed,getter是全局的,computed是组件内部使用的。
  getters: {
    getNums(state) {
      return state.nums
    }
  },
  mutations: {
  },
  actions: {
  },
  modules: {
  }
})

目录:Home.vue

<template>
  <div class="home">
      //采用$store.getters下的getNums方法,可以在多个组件中实现代码复用
     <h1>Home页面的数字:{{this.$store.getters.getNums}}</h1>
  </div>
</template>

<script>
export default {
  name: 'Home'
}
</script>

三、mutations:

更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。

Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数。

不能直接调用一个 mutation handler。这个选项更像是事件注册:“当触发一个类型为 increment 的 mutation 时,调用此函数。”要唤醒一个 mutation handler,你需要以相应的 type 调用 store.commit 方法:

store.commit('increment')

目录:store/index.js

<script>
  export default new Vuex.Store({
  //state相当于组建中的data,专门用来存放全局的数据
  state: {
    nums: "0"
  },
  // getters相当于组件中的computed,getter是全局的,computed是组件内部使用的。
  getters: {
    getNums(state) {
      return state.nums
    }
  },
  //mutations相当于组件中的methods,但是它不能使用异步方法(定时器、axios)
  mutations: {
    //让num累加
    //payload是一个形参,如果组件在commit时,有传这个参数过来,就存在,如果没有传过来,就是undefined
    increase(state, payload) {
      state.nums += payload ? payload : 1
    }
  },
  actions: {
  },
  modules: {
  }
})
</script>

目录:Btn.vue

<template>
    <div>
        <button @click="add">点击加1</button>
    </div>
</template>

<script>
    export default {
        name: "Btn",
        methods: {
            add() {
                //不能直接调用一个 mutation handler,调用store.commit方法
                this.$store.commit("increase")
            }
        }
    }
</script>

四、actions:

actions专门用来处理异步,实际修改状态值的,依然是mutations

  • Action 提交的是 mutation,而不是直接变更状态。
  • Action 可以包含任意异步操作。

理解:actions可以看做是调用了mutations,所以我们使用的需要调用 context来执行commit方法,类似mutations中的store.commit方法。然后在使用 store.dispatcher()来调用actions中定义的方法

目录:store/index.js

export default new Vuex.Store({
  //state相当于组建中的data,专门用来存放全局的数据
  state: {
    nums: "0"
  },
  // getters相当于组件中的computed,getter是全局的,computed是组件内部使用的。
  getters: {
    getNums(state) {
      return state.nums
    }
  },
  //mutations相当于组件中的methods,但是它不能使用异步方法(定时器、axios)
  mutations: {
    decrease(state){
        state.nums--
    }
  },
  //actions专门用来处理异步,实际修改状态值的,依然是mutations
  actions: {
    //点击了“减1”按钮后,放慢一秒在执行减法
    decreaseAsync(context){
      context.commit("decrease")
    }
  },
  modules: {
  }
})

目录:Btn.vue

<template>
    <div>
        <button @click="decrease">点击减1</button>
    </div>
</template>

<script>
    export default {
        name: "Btn",
        methods: {
            decrease() {
                this.$store.dispatch("decreaseAsync")
            }
        }
    }
</script>

五、mapState, mapGetter, mapMutations, mapActions辅助函数

mapState和mapGetters在组件中都是写在computed里面;

mapMutations和mapActions在组件中都是写在methods里面。

mapXXX辅助函数,在调用的时候,在前面加的 ...mapXXX(['参数1','参数二'])...代表的意思是java中的多个参数的意思
目录:Map.vue

mapState和mapGetters在组件中都是写在computed里面;

<template>
    <div>
        <h3>Home页面的数字: {{nums}}</h3>
        <h3>Home页面的数字: {{getNums}}</h3>
    </div>
</template>

<script>
    import { mapState, mapGetters} from 'vuex'
    export default {
        name: "Map",
        computed: {
            //映射this.nums为this.$store.state.nums
            ...mapState(['nums']),
            //映射this.getNums()为this.$store.getters.getNums
            ...mapGetters(['getNums'])
        }
    }
</script>

目录: Map2.vue

mapMutations和mapActions在组件中都是写在methods里面。

调用方法的时候这里需要加上(),要不然会出错。别的地方的方法可以省略().

<template>
    <div>
        <button @click="increase()">点击加1</button>
        <button @click="decreaseAsync()">点击异步减1</button>
    </div>
</template>

<script>
    import {mapMutations, mapActions} from 'vuex'
    export default {
        name: "Map2",
        methods: {
            ...mapMutations(['increase']),
            ...mapActions(['decreaseAsync'])
        }
    }
</script>

六、拆分写法

Store中的所有属性,都可以拆分成单独的js文件来书写

1、拆分前的目录结构:store/index.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  //state相当于组建中的data,专门用来存放全局的数据
  state: {
    nums: "0"
  },
  // getters相当于组件中的computed,getter是全局的,computed是组件内部使用的。
  getters: {
    getNums(state) {
      return state.nums
    }
  },
  //mutations相当于组件中的methods,但是它不能使用异步方法(定时器、axios)
  mutations: {
    //让num累加
    //payload是一个形参,如果组件在commit时,有传这个参数过来,就存在,如果没有传过来,就是undefined
    increase(state, payload) {
      state.nums += payload ? payload : 1
    },
    decrease(state){
      state.nums--
    },

    //结合Btn2.vue,测试参数的传递
    increaseMore(state, payload) {
      state.nums = Number(payload.amount) + Number(state.nums)
    }
  },
  //actions专门用来处理异步,实际修改状态值的,依然是mutations
  actions: {
    //点击了“减1”按钮后,放慢一秒在执行减法
    decreaseAsync(context){
      context.commit("decrease")
    }
  },
  modules: {
  }
})

2、拆分后的目录结构:

image.png

目录:index.js

import Vue from 'vue'
import Vuex from 'vuex'
import state from "./state";
import getters from "./getters";
import mutations from "./mutations";
import actions from "./actions";

Vue.use(Vuex)

export default new Vuex.Store({
  //state相当于组建中的data,专门用来存放全局的数据
  state,
  // getters相当于组件中的computed,getter是全局的,computed是组件内部使用的。
  getters,
  //mutations相当于组件中的methods,但是它不能使用异步方法(定时器、axios)
  mutations,
  //actions专门用来处理异步,实际修改状态值的,依然是mutations
  actions,
  modules: {
  }
})

其他的state.js, getters.js, mutations.js, actions.js等文件都是相当于原来的index.js文件中对应部分拆分出来。用export default {}来表示。

目录:state.js

export default {
    nums: "0"
}

目录: mutations.js

export default {
    //让num累加
    //payload是一个形参,如果组件在commit时,有传这个参数过来,就存在,如果没有传过来,就是undefined
    increase(state, payload) {
        state.nums += payload ? payload : 1
    },
    decrease(state){
        state.nums--
    },
    //结合Btn2.vue,测试参数的传递
    increaseMore(state, payload) {
        state.nums = Number(payload.amount) + Number(state.nums)
    }
}

七、modules:

image.png

我们的store可以认为是一个主模块,它下边可以分解为很多子模块,子模块都可以单独拎出来写,写完在导入到主模块中,下面以users子模块举例:

users模块也可以拥有 state,getters, mutations和actions

所有的方法和属性,该怎么写就怎么写,但users和index.js文件中,需要写入namespace: true命名空间。

然后 store的index.js中引入到modules中。

在组件中获取值的方法:

$stoe.state.users.nickName

在组件中出发mutations的方法:

methods: {
	...mapMutations({
		'changeNickName': 'users/changeNickName'
	})
}
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页