引用官网的话:Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态
这里是它的官方文档:https://vuex.vuejs.org/zh-cn/
我们可以很直观的看到有五个方法:
- State 可以简单的理解为组件的data,不过state是全局唯一的。
- Getters 可以在模板中静态的显示数据。换句话说,getters 可以读取数据,但不能改变状态。
- Mutations 允许更新状态,但永远是同步的。Mutations 是 store 中改变状态数据的唯一方式。
- Actions 允许异步更新状态,但是需要使用一个已经存在的 mutation 。如果你需要以特定的顺序同时执行不同的 mutations 会非常有用。
- Modules Vuex 允许我们将 store 分割到模块(module)。每个模块拥有自己的 state、mutation、action、getters、甚至是嵌套子模块——从上至下进行类似的分割
一、简单demo
搭建一个vue-cli,新建一个store.js
在main.js种先引入vuex
// The Vue build version to load with the `import` command // (runtime-only or standalone) has been set in webpack.base.conf with an alias. import Vue from 'vue' import App from './App' import router from './router' import {store} from './vuex/store' Vue.config.productionTip = false /* eslint-disable no-new */ new Vue({ el: '#app', router, // 注意这里要注入到vue实例 store, template: '<App/>', components: { App } })
在store.js种引用vuex
import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); export const store = new Vuex.Store({ state: { counter: 8, weather: 'rainy', time: '20:40' }, // 展示内容,无法改变状态 getters: { counter: state => { return state.counter }, weather: state => { return state.weather }, time: state => { return state.time } }, //mutations 永远是同步的 mutations: { // 显示传递的载荷 payload, 用 num 表示 increment: (state, num) => { state.counter += num; }, decrement: (state, num) => { state.counter = state.counter - num; } }, // actions 可异步 actions: { acDecremen:({commit}, asyncNum) => { setTimeout(() => { // asyncNum 对象可以是静态值 commit('decrement', asyncNum.num); }, 1000); } }, });
在app.vue种拿到数据
<template> <div id="app"> {{counter}} || {{weather}} || {{time}} <button @click='add'> +1 </button> <button @click='increment'> -1 </button> </div> </template> <script> export default { computed: { counter() { return this.$store.getters.counter }, weather() { return this.$store.getters.weather }, time() { return this.$store.getters.time } }, methods: { add(){ this.$store.commit('increment',1) }, increment(){ this.$store.dispatch('acDecremen',{num:1}) } } } </script> <style> #app { font-family: 'Avenir', Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px; } </style>
运行:一个按钮立即加一(mutations),一个一秒后减一(actions)
二、利用vuex实现子组件间的通讯
我们先注册几个子组件
/*App.vue*/ import music from './components/music' import movie from './components/movie' new Vue({ //.......... components:{ music, movie } }) /*music.vue*/ <template> <div class = 'music'> I'm music,my counter is {{counter}} </div> </template> <script> export default{ computed:{ counter() { return this.$store.getters.counter }, } }; </script> <style> </style> /*movie.vue*/ <template> <div class = 'movie'> I'm movie,my counter is {{counter}} </div> </template> <script> export default{ computed:{ counter() { return this.$store.getters.counter }, } }; </script> <style> </style>
然后在app.vue种直接使用模板,就可以同步更新数据了
三、Module
感觉这个功能有点像命名空间的功能,其中的getters,mutations,actions现在仍然注册在全局命名空间——这样保证了多个模块能够响应同一 mutation 或 action。
即 getters,mutations,actions的名字不可以重复
修改store.js
import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); const moduleA = { state: { name: 'moduleA' }, getters: { aname: state => state.name }, mutations: { setBName: state => state.name = 'new modulesA' }, actions: { acSetAName: state => state.name = 'ac moudleA' } } const moduleB = { state: { name: 'moduleB' }, getters: { bname: state => state.name }, mutations: { setBName: state => state.name = 'new modulesB' }, actions: { acSetBName: state => state.name = 'ac moudleB' } } export const store = new Vuex.Store({ modules: { a: moduleA, b: moduleB } })
想拿到moduleA的name的值可以不用getters,直接
this.$store.state.a.name
其他方法的调用都一样,因为都是不同的方法名