概念
专门在Vue中实现集中式状态 (数据) 管理的一个Vue插件,对vue中多个组件的共享状态进行集中式的管理(读/写) ,适用于任意组件之间的通信
使用场景:
- 多个组件依赖于同一个状态(数据)的时候
- 来自不同组件的行为(事件),都要变更(操作) 同一状态(数据)
- 在多个路由视图中都能访问的一个组件,这个组件就叫全局组件,它所依赖的数据也要放在全局管理
网络异常,图片无法展示
|
vuex的组成
- Actions --> 响应组件dispatch派遣的方法,处理业务逻辑和发Ajax请求等,然后commit提交给Mutations
- Mutations --> 接收Actions提交的方法和数据,获取存储数据的state,并且操作、处理数据
- State --> 保存数据
网络异常,图片无法展示
|
补充:
若组件vc派遣的方法没有业务逻辑也不用发Ajax请求数据,则可以越过Actions,直接与Mutations对话
可以在methods声明方法的时候,直接通过vc上的$store里面的commit( ) ,将方法和数据提交给Mutations对象
export default { name: 'Count', data(){ return { number: 1 // 用户选择的数 } }, methods: { // 下面的加法运算和减法运算都不需要额外的逻辑运算,也不用发Ajax请求数据 // 故跳过dispatch给actions对象的阶段,直接commit提交给mutations对象 // 而和为奇数再加的方法需要先做奇数判断,所以要dispatch给actions对象 increment(){ this.$store.commit('increment',this.number) }, decrement(){ this.$store.commit('decrement',this.number) }, incrementOdd(){ this.$store.dispatch('incrementOdd', this.number) // 和为奇数再加 } } }
搭建Vuex的环境
- 安装vuex
npm i vuex
- 配置store选项
法一:在src文件夹内新建一个vuex文件夹,在里面创建一个store.js
法二:在src文件夹内新建一个store文件夹,在里面创建一个index.js(官方)
// 创建文件src/store/index.js // 用于创建vuex中最核心的store // 引入Vue import Vue from 'vue' // 引入Vuex import Vuex from 'vuex' // 应用Vuex插件 Vue.use(Vuex) // 准备actions对象--用于响应组件中用户的动作 const actions = {} // 准备mutations对象--用于修改state中的数据 const mutations = {} // 准备state对象--用于保存数据 const state = {} // 准备getters对象 --对state中的数据进行加工处理(类似于computed,无需求可以不写) const getters = { // 处理函数 处理函数形参传入state,通过处理函数的return返回数据 } // 创建store,并配置上面准备好的对象 const store = new Vuex.store({ actions, mutations, state, getters // 没有准备getters对象,则配置可以不写 }) // 暴露store export default store
在main.js中创建vm时传入store配置项
// 在main.js中 // 引入store import store from './store/index.js' // 创建vm const vm = new Vue({ el: '#app', render: h => h(App), store // 传入store配置项 store:store的简写 })
补充
为什么别的插件都是在main.js中引入和使用,而Vuex要在创建store的文件中引入和使用?
知识点:在js代码执行时,所有的import代码会被提升,优先解析执行
如果在main.js中引入和使用Vuex,这会导致在引入store 和 创建vm时传入store配置选项 的过程中,引入store的import语句会被提升,优先执行。而此时使用Vuex的语句Vue.use(Vuex)还没执行,也就还没有创建好store,所以被提升的引入store的语句会报错
vuex的使用流程:
- 将数据放到src/store/index.js文件下的state对象中
- 在组件中methods节点下声明方法,要通过vc上的$store里面的dispatch派遣方法名和传递的参数
methods: { increment(){ // this.$store.dispatch('fnName', value) this.$store.dispatch('increment', this.number) // 加法,每次加data中number的值 }, decrement(){ // this.$store.dispatch('fnName', value) this.$store.dispatch('decrement', this.number) // 加法,每次减data中number的值 }, incrementOdd(){ // this.$store.dispatch('fnName', value) this.$store.dispatch('incrementOdd', this.number) // 和为奇数再加 }, incrementWait(){ this.$store.dispatch('incrementWait', this.number) // 等1秒后再加 } }
- 在src/store/index.js文件下的actions对象中根据上面的dispatch声明相应的方法。这个方法有两个参数,一个是类似mini版store的对象, 官方将其命名为context,里面有commit、dispatch等方法,还有state、getters的数据;另一个参数就是上面传入的值value。 此时,actions要做的是将接收到的方法和数值commit提交到mutations中,真正执行方法和处理数据的是mutations
const actions = { increment(context, value){ // context.commit('fnName', value) fnName和value就是dispatch传过来的 context.commit('increament', value) // commit提交 }, decrement(context, value){ context.commit('decreament', value) }, incrementOdd(context, value){ // 在actions中处理业务逻辑 if(context.state.sum % 2){ // 加入业务逻辑,和为奇数 再提交该方法和数值 context.commit('increament', value) // 注意这已经是判断内了,提交的是increament } }, incrementWait(context, value){ setTimeout(()=>{ context.commit('increament', value) },1000) } }
- 在mutations对象中操作数据,mutations中的方法都有两个参数,一个是state中的数据,一个是传入的要操作的值value
const mutations = { // mutations中不要写任何业务逻辑和Ajax请求 increment(state,value){ state.sum += value }, decrement(state,value){ state.sum -= value } }