Vuex重要知识点总结

介绍

Vuex 是⼀个专为 Vue.js 应⽤程序开发的状态管理模式。它采⽤集中式存储管理应⽤的所有组件的状态,并以相应的规则保证状态以⼀种可预测的⽅式发⽣变化。

vuex

安装Vuex

vue add vuex
复制代码

Store.js

import Vue from 'vue';
import Vuex from 'vuex';
//确保开头调用Vue.use(Vuex)
Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    //this.$store.state.count
    count: 0
  },
  getters: {
    evenOrOdd: (state) => {
      //this.$store.getters.evenOrOdd
      return state.count % 2 === 0 ? '偶数' : '奇数'
    }
  },
  mutations: {
    increment(state) {
      //this.$store.commit('increment')
      state.count++
    },
    decrement(state) {
      //this.$store.commit('decrement')
      state.count--
    }
  },
  actions: {
    increment({commit}) {
      //this.$store.dispatch('increment')
      //修改状态的唯一方式是提交mutation
      commit('increment');
    },
    decrement({commit}) {
      //this.$store.dispatch('incrementAsync')
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          commit('increment');
          resolve(10);
        }, 1000);
      })
    }
  }
})
复制代码

我们可以在组件的某个合适的时机通过this.$store.state来获取状态对象,以及通过this.$store.commit方法触犯状态变更

this.$store.commit('increment')
复制代码

mapState辅助函数

当一个组件需要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余。为了解决这个问题,我们可以使用mapState辅助函数帮助我们生成计算属性

//在单独构建的版本中辅助函数为Vuex.mapState
import {mapState} from 'vuex'

export default {
  //...
  computed: mapState({
    //箭头函数可以使代码更简练
    count: state => state.count,
    
    //传字符串参数'count'等同于'state => state.count'
    countAlias: 'count',
    
    //为了能够使用`this`获取局部状态,必须使用常规函数
    countPlusLocalState(state) {
      return state.count + this.localCount
    }
  })
}
复制代码

当映射的计算属性的名称与state的子节点名称相同时,我们也可以给mapState传一个字符串数组。

computed: mapState([
	//映射 this.count 为 store.state.count
	'count'
])
复制代码

对象展开运算符

mapState函数返回的是一个对象。我们如何将它与局部计算属性混合使用呢?通常,我们需要一个工具函数将多个对象合并为一个,以使我们可以将最终对象传给computed属性。但是自从有了对象展开运算符,极大地简化了写法

computed: {
	...mapState({
		"count"
	})
}
复制代码

mapGetters辅助函数

mapGetters辅助函数仅仅是将store中的getter映射到局部计算属性:

import {mapGetters} from 'vuex'

export default {
	//...
	computed: {
		...mapGetters([
			'evenOrOdd'
		])
	}
}
复制代码

如果你想将一个getter属性另取一个名字,使用对象形式:

mapGetters({
	//把`this.doneEvenOrOdd`映射为`this.$store.getters.evenOrOdd`
	doneEvenOrOdd: 'evenOrOdd'
})
复制代码

Mutation

更改Vuex的store中的状态的唯一方法是提交mutation。Vuex中的mutation与拥有一个字符串的**事件类型(type)和一个回调函数(handler)**的事件十分类似。这个回调函数就是我们实际进行状态更改的地方,并且它会接state作为第一个参数。

MapMutation辅助函数

你可以在组件中使用this.$store.commit('xxx')提交mutation,或者使用mapMutations辅助函数将组件中的methods映射为store.commit调用(需要在根节点注入store)。

import {mapMutations} from 'vuex'
export default {
	//...
	methods: {
		...mapMutations('counter', [
			'increment',
			'decrement',
		])
	}
}
复制代码

Action

Action类似于mutation,不同在于:

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

MapAction辅助函数

import {mapMutations} from 'vuex'

export default {
	//...
	methods: {
		...mapAction('counter', [
			'incrementAsync'
		])
	}
}
复制代码

提交方式

//在组件内部
//以载荷形式分发
this.$store.dispatch('incrementAsync', {
  amount: 10
})

//以对象形式分发
this.$store.dispatch({
  type: 'incrementAsync',
  amount: 10
})
复制代码

Module

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

为了解决以上问题,Vuex允许我们将store分割成模块(moudle)。每个模块拥有自己的state、mutation、action、getter,甚至是嵌套子模块一一从上至下进行同样方式的分割:

做一个购物车案例

有两个模块cartproducts

创建store文件夹

|--- store
    |--- index.js
    |___ modules
        |--- cart.js
        |___ products.js
复制代码

cart.js

如果希望你的模块具有更高的封装度和复用性,你可以通过添加namespaced: true的方式使其成为带命名空间的模块

当模块被注册后,它的所有getter、action及mutation都会自动根据模块注册的路径调整命名。

export default {
	//使当前模块具有更高的封装度和复用性
	namespaced: true,
	state: {
		...
	},
	getters: {
		...
	},
	mutations: {
		...
	},
	actions: {
		...
	},
}
复制代码

products.js

export default {
	//使当前模块具有更高的封装度和复用性
	namespaced: true,
	state: {
		...
	},
	getters: {
		...
	},
	mutations: {
		...
	},
	actions: {
		...
	},
}
复制代码

index.js

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
import cart from './modules/cart';
import products from './modules/products';
export default new Vuex.Store({
	modules: {
		cart,
		products,
	}
})
//this.$store.state.cart //获取cart的状态
//this.$store.state.products //获取products的状态
复制代码

什么情况下我应该使用Vuex?

Vuex可以帮助我们管理共享状态,并附带了更多的概念和框架。这需要对短期和长期效益进行权衡。

如果您不打算开发大型单页应用,使用Vuex可能是繁琐冗余的。确实如此——如果您的应用够简单,您最好不要使用Vuex。一个简单的store模式就足够您所需了。但是,如果您需要构建一个中大型单页应用,您很可能会考虑如何更好地在组件外部管理状态,Vuex将会成为自然而然的选择。引用Redux的作者Dan Abramov的话说就是:

Flux架构就像眼镜:您自会知道什么时候需要它

插件

日志插件

Vuex自带一个日志插件用于一般的调试:

import createLogger from 'vuex/dist/logger'
const store = new Vuex.store({
	plugins: [createLogger({
		collapsed: false,//自动展开记录的mutation
	})]
})
复制代码

要注意,logger插件会生成状态快照,所以仅在开发环境使用。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享