八、vuex
一、概念
Vuex是一个专为Vue.js应用程序开发的状态管理模式
通俗讲就是把多个组件共享的变量全部存储在一个对象里面
二、使用方式
vuex不是vue内置的,但是是官方的
使用步骤
安装vuex
创建store对象管理数据
挂载store对象到vue实例
-
安装vuex
npm i -S vuex
-
-
创建
src/store
目录,并在其中创建index.js文件用于导入并创建store对象 -
编写
src/store/index.js
-
1 import Vue from 'vue' 2 import Vuex from 'vuex' 3 4 Vue.use(Vuex) 5 6 export default new Vuex.Store({ 7 state: { 8 }, 9 mutations: { 10 }, 11 actions: { 12 }, 13 getters:{ 14 }, 15 modules: { 16 } 17 })
1 import Vue from 'vue' 2 import App from './App.vue' 3 import router from './router' 4 // 引入store 5 import store from './store' 6 7 Vue.config.productionTip = false 8 9 new Vue({ 10 router, 11 // 使用store 12 store, 13 render: h => h(App) 14 }).$mount('#app')
三、核心概念
1、state
state提供唯一公共数据源,所有的共享数据都要统一放到state中进行存储
1 // 在组件中访问state数据的第一种方式 2 this.$store.state.全局数据名称
1 // 在组件中访问state数据的第二种方式,按需导入mapState函数 2 // 将全局函数映射为当前组件的计算属性,数据的使用方式如同在当前组件中使用自身的data数据一样 3 import { mapState } from 'vuex' 4 computed: { 5 ...mapState(['count']) 6 }
2、mutations
mutations用于变更store中的数据
在Vuex中只能通过mutation变更store中的数据,不可以直接操作store中的数据
通过这种方式操作起来稍微繁琐一些,但是可以集中监控所有数据的变化
不要在mutation中写异步的代码
1 const store = new Vuex.Store({ 2 state: { 3 count: 1 4 }, 5 mutations: { 6 // state是默认参数 7 increment (state) { 8 // 变更状态 9 state.count++ 10 } 11 } 12 })
1 // 组件中触发mutation的第一种方式 2 methods:{ 3 handle(){ 4 this.$store.commit('increment') 5 } 6 }
1 // 组件中触发mutation的第二种方式 2 import { mapMutations } from 'vuex' 3 4 methods:{ 5 ...mapMutations(['increment','add']), 6 handle1(){ 7 this.increment() 8 }, 9 handle2(){ 10 this.add([arg1,...]) 11 } 12 }
- 可以向
store.commit
传入额外的参数,即 mutation 的 载荷(payload):
1 // ... 2 mutations: { 3 increment (state, n) { 4 state.count += n 5 } 6 }
1 store.commit('increment', 10)
3、actions
action类似于mutation
action 提交的是 mutation,而不是直接变更状态
action 可以包含任意异步操作
1 // store/index.js中声明action 2 const store = new Vuex.Store({ 3 // 省略其他代码 4 mutations: { 5 add(state){ 6 state.count++ 7 } 8 }, 9 actions: { 10 addAsync(context, [arg1,...]){ 11 setTimeout(() => { 12 context.commit('add', [arg1,...]) 13 },1000) 14 } 15 } 16 })
组件中使用
1 // 组件中触发action的第一种方式 2 methods: { 3 handle(){ 4 this.$store.dispach('addAsync', [arg1,...]) 5 } 6 }
1 // 组件中触发action的第二种方式 2 import { mapActions } from 'vuex' 3 4 export default { 5 // ... 6 methods: { 7 ...mapActions([ 8 'addAsync' // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')` 9 ]) 10 } 11 }
4、getters
对store中已有的数据加工处理形成新的数据
对已有的数据进行加工,类似于Vue的计算属性,getter 的返回值会根据它的依赖被缓存起来
store数据发生变化,则getter中的数据也会跟着变化
1 // 定义getter 2 .... 3 getters: { 4 showNum: state => { 5 return '当前最新的数量是【' + state.count + '】' 6 } 7 }
使用
1 // 在组件中访问getters数据的第一种方式 2 this.$store.getters.全局数据名称
1 // 在组件中访问getters数据的第二种方式,按需导入mapGetters函数 2 import {mapGetters} from 'vuex' 3 // 将全局函数映射为当前组件的计算属性 4 export default { 5 // ... 6 computed: { 7 ...mapGetters(['showNum']) 8 } 9 }
- Getter 也可以接受其他 getter 作为第二个参数:
1 getters: { 2 // ... 3 getters: { 4 doneTodos: state => { 5 return state.todos.filter(todo => todo.done) 6 } 7 }, 8 doneTodosCount: (state, getters) => { 9 return getters.doneTodos.length 10 } 11 }
5、modules
当应用变得非常复杂时,store 对象就有可能变得相当臃肿
因此Vuex 允许我们将 store 分割成模块(module)。
每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块 ===> 从上至下进行同样方式的分割
1 const moduleA = { 2 state: () => ({ ... }), 3 mutations: { ... }, 4 actions: { ... }, 5 getters: { ... } 6 } 7 8 const moduleB = { 9 state: () => ({ ... }), 10 mutations: { ... }, 11 actions: { ... } 12 } 13 14 const store = new Vuex.Store({ 15 modules: { 16 a: moduleA, 17 b: moduleB 18 } 19 }) 20 21 store.state.a // -> moduleA 的状态 22 store.state.b // -> moduleB 的状态
- module中的mutations
1 const moduleA = { 2 state: () => ({ 3 name: 'zhangsan' 4 }), 5 mutations: { 6 updateName (state, payload) { 7 // 这里的 `state` 对象是模块的局部状态 8 state.name = payload 9 } 10 } 11 }
1 // 组件中使用 2 methods: { 3 updateName() { 4 this.$store.commit('updateName', 'lisi') 5 } 6 }
module中的getters
1 const moduleA = { 2 state: () => ({ 3 name: 'zhangsan' 4 }), 5 mutations: { 6 updateName (state, payload) { 7 // 这里的 `state` 对象是模块的局部状态 8 state.name = payload 9 } 10 }, 11 getters: { 12 fullName(state) { 13 return state.name + '1111' 14 }, 15 // 第二个参数用来操作getters中的getter 16 fullName2(state, getters) { 17 return getters.fullName + '2222' 18 }, 19 // 第三个参数操作根state 20 fullName3(state, getters, rootState) { 21 return getters.fullName2 + rootState.count 22 } 23 } 24 }
1 // 组件中使用 2 <div>{{$store.getters.fullName}}</div> 3 <div>{{$store.getters.fullName2}}</div> 4 <div>{{$store.getters.fullName3}}</div> 5 // 或者 6 methods: { 7 updateName() { 8 this.$store.getters.fullName() 9 } 10 }
- module中的actions
1 const moduleA = { 2 state: () => ({ 3 name: 'zhangsan' 4 }), 5 mutations: { 6 updateName (state, payload) { 7 // 这里的 `state` 对象是模块的局部状态 8 state.name = payload 9 } 10 }, 11 actions: { 12 aUpdateName() { 13 setTimeout(() => { 14 context.commit('updateName', 'wangwu') 15 }, 1000) 16 } 17 } 18 }
1 // 组件内使用 2 methods: { 3 asyncUpdateName() { 4 this.$store.dispatch('aUpdateName') 5 } 6 }