npm install vuex // 或者yarn add vuex
2. 在项目根目录新建 store/index.js ,引入、挂载vuex并创建vuex对象:
import Vue from 'vue'import Vuex from 'vuex'//挂载VuexVue.use(Vuex)//创建VueX对象const store = new Vuex.Store({ state:{ name:'helloVueX' }})export default store
3. 将store挂载到vue实例中——main.js
import Vue from 'vue'import App from './App'import router from './router'import store from './store'Vue.config.productionTip = falsenew Vue({ el: '#app', router, store, // 将状态从根组件注入到所有子组件,方便在组件中获取状态。 render: h => h(App)})
二、Vuex核心概念
Vuex使用单一状态数,也就是说一个应用只包含一个store实例对象,这个对象包含所有应用层的状态。这个唯一的数据源就是store对象中的state。
1. statestate对象中的键值对就是我们要管理的状态。
在组件中可以在computed中通过this.$store.state.xxx来获取具体的状态值,如:
const Counter = { template: `
{{count}}
`, computed: { count(){ return this.$store.state.count } }}
我们还可以使用mapState辅助函数来生成计算属性,这在一个组件需要获取多个状态时很方便。使用方法如下:
// 先引入mapState函数import { mapState } from 'vuex'export default { computed: mapState({ count: state => state.count, }), // 这种计算属性名和state的子节点名相同的,还可以写成下面的形式 computed: mapState([ 'count' ]) // 如果要和其他计算属性混合使用,还能使用对象展开运算符 computed: { localComputed(){}, ...mapState(['count']) }}
2. Getter
Getter可以看作store的计算属性,getter的返回值会根据依赖缓存起来,依赖值变化时才会重新计算。第一个参数是state,第二个参数可以是其他getter。在组件中可以通过this.$store.getters.xxx来访问。
const store = new Vuex.store({ state: { todos: [ { id: 1, text: '...', done: true}, { id: 2, text: '...', done: false}, ] }, getters: { doneTodos: state => { return state.todos.filter(todo => todo.done) }, doneTodosCount: (state, getters) =>{ return getters.doneTodos.length } }})// 组件中访问this.$store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }]this.$store.getters.doneTodosCount // 1
我们还可以使用mapGetters辅助函数将store中的getter映射到计算属性:
import { mapGetters } from 'vuex'export default { computed: { // 使用对象展开运算符将 getter 混入 computed 对象中 ...mapGetters([ 'doneTodosCount', 'anotherGetter' ]) // 也可以使用对象形式 ...mapGetters({ doneCount: 'doneTodosCount' }) }}
3. Mutation
用来更改store的状态,类似事件,第一个参数state。
(1)在vuex中通过store.commit方法同步修改store数据。
(2)在组件中通过this.$store.commit调用,也可以使用mapMutation将组件中的methods映射为store.commit调用。
mutations:{ // mutation必须是同步函数 changeUrl(state, options){ state.url = options.url; }},actions: { // 两种方式 store.comit('changeUrl', { url: 'https://sdgdfg.com/dgdfgfdg' }); // 或 store.commit({ type: 'changeUrl', amount: 10 })}// 在组件中调用import { mapMutations } from 'vuex'methods: { ...mapMutations([ 'changeUrl' ])}
4. Actions
action可以提交mutation,而不是直接变更状态,它可以完成异步操作(异步操作完成的回调函数中,使用commit触发mutation变更state中的数据)。可以认为action存在的优势就是弥补mutation不能执行异步操作的不足。
(1)在vuex中通过store.dispatch触发action。
(2)在组件中使用this.$store.dispatch,也可以使用mapActions将组件中的methods映射为store.dispatch。
actions: { incrementAsync ({commit}) { setTimeout(() => { commit('increment') }, 1000) }}// 方法1:store.dispatch方法触发action操作store.dispatch('incrementAsync')// 方法2:以载荷形式分发 store.dispatch('incrementAsync', { amount: 10})// 方法3:以对象形式分发store.dispatch({ type: 'incrementAsync', amount: 10})// 组件中import { mapActions } from 'vuex'export default { methods: { ...mapActions([ 'increment', // 将this.increment映射为this.$store.dispatch('increment') ]) }}
用一张图来总结一下:
5. Module
如果应用很复杂造成store臃肿,我们还可以将store分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter,甚至是嵌套子模块。结构大概是这样的:
const moduleA = { state: () => ({ ... }), mutations: { ... }, actions: { ... }, getters: { ... }}const moduleB = { state: () => ({ ... }), mutations: { ... }, actions: { ... }}const store = new Vuex.Store({ modules: { a: moduleA, b: moduleB }})store.state.a // -> moduleA 的状态store.state.b // -> moduleB 的状态
(1)模块内部的 mutation 和 getter,接收的第一个参数是模块的局部状态对象。
(2)模块内部的action中,局部状态是context.state,根节点状态为 context.rootState。
(3)模块内部的 getter,根节点状态会作为第三个参数暴露出来。
其他内容小伙伴们自己看文档吧~要下班了,心已经飞去自由的远方了~