vuex

100 阅读2分钟

仓库vuex

为了方便实现组件之间的数据共享,Vuex用来实现vue组件全局状态(全局状态也就是数据)管理的一种机制。

image.png

vuex特点:

能够在vuex中集中管理共享的数据,易于开发和后期维护

能够高效地实现组件之间的数据共享,提高开发效率

存储在 vuex中的数据都是响应式的,能够实时保持数据与页面的同步

一般情况下,只有组件之间共享的数据,才有必要存储到vuex中;对于组件中的私有数据,依旧存储在组件自身的data中即可。

引入vuex

//main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

Vue.config.productionTip = false

把仓库挂载到vm对象:

new Vue({
  router,
  //挂载以后,所有的组件就可以直接从store中获取全局数据
  store,
  render: h => h(App)
}).$mount('#app')
//引入vuex
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
  //用于保存所有组件的公共数据的对象
  },
  getters: {
  },
  mutations: {
  // 用来修改state和getters里面的数据
  },
  actions: {
  },
  modules: {
  }
})

仓库 store的5个属性

state

state对象类型,类似于组件实例的 data属性,用于保存所有组件的公共数据的对象

export default new Vuex.Store({
  state: {
    msg:'我就是所有共享的数据'
  },
  getters: {
  // 相当于计算属性
  },
  mutations: {
  // 用来修改state和getters里面的数据,相当于methods
  },
  actions: {
  // vuex中用于发起异步请求
  },
  modules: {
  // 拆分模块
  }
})

组件中访问数据

this.$store.state.msg

getters

getters对象类型,类似于实例的计算属性 computed,也就是计算属性。vuex的官方文档也是说到可以将getter理解为store的计算属性,getters的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。它会传入state对象供我们操作,传入的state是最后一次被修改的state对象。

export default new Vuex.Store({
  state: {
    msg:'我就是所有共享的数据',
    products: [
      {name: '鼠标', price: 20,id:1,count:1},
      {name: '键盘', price: 40,id:2,count:1},
      {name: '耳机', price: 60,id:3,count:1},
      {name: '显示屏', price: 80,id:4,count:1}
    ]
  },
  getters: {
    total(state){
      return state.products.reduce((n1,n2)=>{
        return n1+n2.price;
      },0)
    }
  },
  mutations: {
  },
  actions: {
  },
  modules: {
  }
})

组件中使用数据

this.$store.getters.total

mutations

mutations对象类型,类似于实例的 methods,但是必须是同步处理,不能处理异步方法。

组件中希望更改 Vuex 的 store 中的状态(数据)的唯一方法是提交 mutation,不要用赋值表达式直接在组件中给store设置新数据。这样设计的原因是只有通过mutation来更新数据,它才会去帮我们通知所有使用数据的组件更新数据刷新UI

先在mutations中注册事件

export default new Vuex.Store({
  state: {
    msg:'我就是所有共享的数据',
    products: [
      {name: '鼠标', price: 20,id:1,count:1},
      {name: '键盘', price: 40,id:2,count:1},
      {name: '耳机', price: 60,id:3,count:1},
      {name: '显示屏', price: 80,id:4,count:1}
    ]
  },
  getters: {
    total(state){
      return state.products.reduce((n1,n2)=>{
        return n1+n2.price*n2.count;
      },0)
    }
  },
  mutations: {
    changecount(state,value){
      //默认传第一个参数传state
      console.log(state,value);
      // 变更状态
      state.products[2].count=value.n;
    }
  },
  actions: {
  },
  modules: {
  }
})

在组件中调用方法commit(提交载荷)

1.直接触发并传值
this.$store.commit('changecount',{n:100})
2.可以以一个对象的形式传入
传入对象时相当于把整个对象作为了第二个参数传入mutations
this.$store.commit({
  type: 'increment',
  n:100
})

image.png

actions

actions 类似于 mutations,不同在于:

  • actions提交的是mutations而不是直接变更状态
  • actions中可以包含任意异步操作, mutations中绝对不允许出现异步
  • actions中的回调函数的第一个参数是context上下文对象,是一个与store实例具有相同属性和方法的对象

在store中定义

export default new Vuex.Store({
  state: {
    msg: '我就是所有共享的数据'
  },
  mutations: {
    change(state,value){
      // 变更状态
      state.msg=value.n;
    }
  },
  actions: {
    //默认第一个参数传一个跟store一样的对象
    increment(context, obj) {
      setTimeout(() => {
        // 提交载荷
        context.commit('change', obj)
      },100)
    }
  },
  modules: {
  }
})

在组件中使用

1.直接分发
this.$store.dispatch('increment',{n:100})
2.以对象形式分发
this.$store.dispatch({
  type: 'increment',
  n:100
})

module

module可用于业务分块开发:由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。

为了解决以上问题,Vuex 允许我们将 store 分割成模块,每个模块拥有自己的 state、mutation、action、getter

在store的index.js中引入模块

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

//在store的index.js中引入模块
import Module1 from './Module1.js'

Vue.use(Vuex)

export default new Vuex.Store({
  
  modules: {
    // 注入模块
    Module1
  }
})

Module1.js

export default{
//局部命名空间(让state的中变量与其他模块中的同名变量不冲突)
    namespaced: true,
    state: {
        msg: '我是Module1的数据',
      },
      getters: {
        getmsg(state) {
          return state.msg+"666666"
        }
      },
      mutations: {
        changecount(state, value) {
          //默认传第一个参数传state
          // 变更状态
          state.msg = value.n;
        },
        change(state,value){
          // 变更状态
          state.msg=value.n;
        }
      },
      actions: {
        //默认第一个参数传一个跟store一样的对象
        increment(context, obj) {
          setTimeout(() => {
            // 提交载荷
            context.commit('change', obj)
          },100)
        }
      }
}

组件中的使用注入的模块:

this.$store.state.Module1.msg // -> Module1的状态
this.$store.commit("Module1/change",100)-> Module1 的mutations
this.$store.getters["Module1/getmsg"]-> Module1的getters
this.$store.dispatch("Module1/change",100)-> Module1 的actions