一篇搞定Vuex
1.简介
首先,你必须明显明白vuex到底是干啥的,主要解决开发中的哪些问题?
Vuex是一个专门为Vue.js应用程序开发的状态管理模式,它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式变化
说白了,就是:提供了那么一个公共存储的地方,存放各个组件的数据,组件访问数据和操作数据访问这个地方即可
所以,Vuex主要解决是组件间数据传递问题,尤其是嵌套组件,项目一大时,父子组件间的数据传递就非常麻烦了,而Vuex则提供了一种集中管理组件数据的方案,当然小型项目就没必要用Vuex了
2.Demo准备
- vue init webpack-simple vuex-demo
- cd vuex-demo
- npm install
- npm install vuex -S
3.访问store对象的两种方式
Vuex的核心是Store(仓库),相当于是一个容器,一个store实例中包含以下属性的方法:
- state 定义属性(状态、数据)
- getters 用来获取属性
- actions 定义方法(动作)
- commit 提交变化,修改数据的唯一方式就是显式的提交mutations
- mutations 定义变化
注:不能直接修改数据,必须显式提交变化,目的是为了追踪到状态的变化
创建store.js文件,在main.js中导入并配置store.选项
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex); //定义属性(数据) var state = { count: 6 } //创建store对象 const store = new Vuex.Store({ state, }) //导出store对象 export default store;
import Vue from 'vue' import App from './App.vue' import store from './store.js' //导入store对象 new Vue({ store, el: '#app', render: h => h(App) })
方式一:通过this.$store访问
//方式1:通过this.$store访问 computed: { count() { return this.$store.state.count; } }
方式二:通过mapState、mapGetters、mapActions访问,vuex提供了两个方法
- mapState 获取state
- mapGetters 获取getters
- mapActions 获取actions
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex); //定义属性(数据) var state = { count: 6 } //定义getters var getters = { count(state) { return state.count; } } //定义actions,要执行的操作,如流程判断、异步请求 const actions = { increment(context) { //包含 commit dispatch state context.commit('increment'); }, decrement(context) { if (context.state.count > 10) { context.commit('decrement'); } } } //定义mutations,处理状态(数据)的改变 const mutations = { increment(state) { state.count++; }, decrement(state) { state.count--; } } //创建store对象 const store = new Vuex.Store({ state, getters, actions, mutations, }) //导出store对象 export default store;
<template> <div id="app"> <button @click="increment">增加</button> <button @click="decrement">减小</button> <p>当前数字为:{{count}}</p> </div> </template> <script> import { mapState, mapGetters, mapActions } from "vuex"; export default { name: "app", data() { return { msg: "Welcome to Your Vue.js App" }; }, //方式1:通过this.$store访问 /*computed: { count() { return this.$store.state.count; } }*/ /*computed:mapState([ 'count' ])*/ computed: mapGetters(["count"]), methods:mapActions([ 'increment', 'decrement', ]) }; </script> <style> </style>
分模块组织Vuex
上面那种方式,所有的都写在一个文件,项目大时,难免看起来显乱,所以需要分模块来组织,原则上就私有和公共的分开进行组织
其中modules存放每个模块的,actions.js,getters.js,mutations.js存放公共的,目录如下
user.js
/** * 用户模块 */ import types from '../types.js' const state={ count:6 } var getters={ count(state){ return state.count; } } const actions = { increment({commit,state}){ commit(types.INCREMENT); //提交一个名为increment的变化,名称可自定义,可以认为是类型名 }, decrement({commit,state}){ if(state.count>10){ commit(types.DECREMENT); } } } const mutations={ [types.INCREMENT](state){ state.count++; }, [types.DECREMENT](state){ state.count--; } } export default { state, getters, actions, mutations }
actions.js
import types from './types.js' const actions={ incrementAsync({commit,state}){ //异步操作 var p=new Promise((resolve,reject) => { setTimeout(() => { resolve(); },3000); }); p.then(() => { commit(types.INCREMENT); }).catch(() => { console.log('异步操作'); }); } } export default actions;
getters.js
const getters={ isEvenOrOdd(state){ return state.user.count%2==0?'偶数':'奇数'; } } export default getters;
types.js
/** * 定义类型常量 */ const INCREMENT='INCREMENT' const DECREMENT='DECREMENT' export default { INCREMENT, DECREMENT }
index.js
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex); import getters from './getters.js' import actions from './actions.js' import user from './modules/user.js' export default new Vuex.Store({ getters, actions, modules:{ user } });
main.js
import Vue from 'vue' import App from './App.vue' import store from './store/index.js' new Vue({ store, el: '#app', render: h => h(App) })
分模块组织的访问
console.log(this.$store); console.log(this.$store.getters['dirTestcaseData']); console.log(this.$store.getters['user/count']); console.log(this.$store.state['project']); console.log(this.$store.state.user['count']); this.$store.dispatch("asset/changeCurrentFundIndex", index); this.$store.dispatch('increment'); //导入 import { mapState, mapGetters } from "vuex"; //批量引入 ...mapGetters("asset", { assetDetailType: "assetDetailType", tradeSelectVal: "tradeSelectVal", totalAsset: "totalAsset" }) //也支持数组