vuex适用于大型单页应用。每一个Vuex应用的核心就是store(仓库),store中储存大量状态,Vuex的状态存储是响应式的。vuex使用单一状态树,一个对象包含了全部的应用层级状态,每个应用仅仅包含一个store实例。调试页面,有可能会用到dev-tools。
一、概念
1、state(共享的状态)
要get状态,需要在计算属性computed中返回状态。要get多个状态,可以借助mapState辅助函数生成计算属性。
state属性在store实例中设置,mapState函数在vue实例的computed属性中写。
state:{ a: '' }
//实例中
computed: { getStateA(){ return store.state.a } }
//组件中 import { mapState } from 'vuex' export default { computed: { ...mapState(['a']), getStateA(){ return this.a; } } }
2、getters(共享的方法,该方法用于get状态)
实现多个组件共享同一个状态,getters属于store的计算属性,根据依赖缓存返回值,当依赖变化时,重新计算。
getters属性在store实例中设置,mapGetters函数在vue实例或组件的computed属性中写。
getters: { getterA: state => { return state.a } }
//实例中
computed: { getGetterA() { return store.getters.getterA } }
//组件中 import { mapGetters } from 'vuex' export default { computed: { ...mapGetters(['getterA']), getGetterA(){ return this.getterA; } } }
3、mutations(修改状态)
mutation必须是同步函数,因为回调函数进行的状态改变不能被追踪,因为mutation触发的时候,回调函数还没有被调用。
mutations属性在store实例中设置,直接修改状态,mapMutations函数在vue实例或组件的methods属性中写。
mutations: { mutationA: state => { state.count++ } }
//实例中
methods: { eventA() { this.$store.commit('mutationA'); } }
//组件中 import { mapMutations } from 'vuex' export default { methods: { ...mapMutations(['mutationA']), eventA(){ this.mutationA(); } } }
4、actions(提交mutation)
store中的状态是响应式的,要set状态,不能直接改变数据,而是需要提交mutation。actions属性在store实例中设置,不会直接变更状态,而是提交mutation,可以包含异步操作。mapActions函数在vue实例或组件的methods属性中写。下面介绍4种提交mutaion的办法,仅供参考。
A、在组件中提交mutation
mutations:{ //改变状态 mutationA(state, { adata }) { state.awords = adata; } }
//全局定义store,在组件中提交mutation methods:{ eventF(adata){ // 以载荷形式提交mutation store.commit('mutationA',{ adata }); } }
//在组件内提交mutation methods:{ eventF(adata){ // 以载荷形式提交mutation this.$store.commit('mutationA',{ adata }); } }
B、在组件中提交mutation之mapMutations
import { mutationA, mutationB } from './mutation-types' export default { [mutationA](state,payload){ state.dataA = payload; }, [mutationB](state,payload){ state.dataB = payload; } }
import { mapMutations } from 'vuex'
export default {
methods: { ...mapMutations([ 'mutationA', 'mutationB' ]), ...mapMutations({ add: 'mutationA' }), eventA(){ this.mutationA(); }, eventB(bdata){ this.mutationB(bdata); }, eventC(cdata){ this.add(cdata); } } }
C、在actions中提交mutation
mutations:{ //改变状态 mutationA(state, payload) { state.awords = payload; }, //改变状态 mutationB(state, payload) { state.bwords = payload; } },
//在actions中提交mutation,同步,异步 actions:{ actionA({commit,state},payload){ commit('mutationA',payload); }, actionB({commit},payload){ new Promise((resolve,reject)=>{ setTimeout(()=>{ commit('mutationB',payload); resolve(); },1000) }) } }
//在组件中分发action methods:{ eventA(){ store.dispatch('actionA','我是老大'); } }
D、在actions中提交mutation之mapActions
import { mutationA, mutationB } from './mutation-types' export default { [mutationA](state,payload){ state.dataA = payload; }, [mutationB](state,payload){ state.dataB = payload; } }
//actions.js,提交mutation import { mutationA, mutationB } from './mutation-types' export default { actionA({commit,state}, payload){ commit(mutationA, payload); }, actionB({commit,state}, payload){ commit(mutationB, payload); } }
import { mapActions } from 'vuex' //在组件中分发action methods:{ ...mapActions(['actionA', 'actionB']), eventA(){ this.actionA('我是老大'); }, eventB(){ this.actionB('我是老二'); } }
5、modules
解决状态多导致store对象臃肿,将store分割成模块,每个模块拥有自己state,getters,mutations,actions。
二、vuex的引用方法
1、用script标签
<script src="https://unpkg.com/vuex"></script>
2、npm安装
cnpm install vuex
//在js文件引入 var Vue = require('vue') var Vuex = require('vuex') Vue.use(Vuex)
三、参考案例
const store = new Vuex.Store({ state:{ fwords: '一朵红花', awords: '我是老大' }, getters:{ getAwords(state){ return state.awords } }, mutations:{ //改变状态 listenA(state, { adata }) { state.awords = adata; } } })
1、父组件给子组件传递消息
//父组件 <com-a :apropVal="getFwords"></com-a> computed:{ getFwords(){ return store.state.fwords } }
//子组件 <h3>父亲给我了,{{ apropVal }}</h3> props:['apropVal']
2、子组件给父组件传递事件
//子组件 <input type="button" value="A和父亲说话" @click="eventAf"> methods:{ eventAf(){ this.$emit('a-f-msg',`谢谢父亲`); } }
//父组件 <com-a @a-f-msg="eventFa"></com-a> methods:{ eventFa(adata){ // 以载荷形式提交mutation store.commit('listenA',{ adata }); } }
const store = new Vuex.Store({ state:{ awords: '', bwords: '' }, getters:{ getAwords(state){ return state.awords }, getBwords(state){ return state.bwords } }, mutations:{ //改变状态 mutationA(state, payload) { state.awords = payload; }, //改变状态 mutationB(state, payload) { state.bwords = payload; } }, actions:{ actionA({commit,state},payload){ commit('mutationA',payload); }, actionB({commit},payload){ new Promise((resolve,reject)=>{ setTimeout(()=>{ commit('mutationB',payload); resolve(); },1000) }) } } })
//子组件A <h4>B传过来的数据是:{{ store.getters.getBwords }}</h4> <input type="button" value="把值传给B" @click="eventAb"> methods:{ eventAb(){ store.dispatch('actionA','我是老大'); } }
//子组件B <h4>A传过来的数据是:{{ store.getters.getAwords }}</h4> <input type="button" value="把值传给A" @click="eventBa"> methods:{ eventBa(){ store.dispatch('actionB','我是老二'); } }
1、语法基础
A、引入和输出模块
//store.js,默认输出 export default store; //main.js import store from 'store.js';
// constants.js export const A = 1; export const B = 3;
//main.js
import { A, B } from './constants.js';
// constants.js,跨模块常量 export const A = 1; export const B = 3; export const C = 4; // main.js import * as constants from './constants'; console.log(constants.A); // 1 console.log(constants.B); // 3
B、对象扩展运算符
将多个对象合并为一个,传给computed属性。
# 安装插件 npm i -D babel-plugin-transform-object-rest-spread #配置文件babelrc { "presets": ["env"], "plugins": ["transform-runtime","transform-object-rest-spread"] }
//组件内
computed:{ ...mapGetters(['getterA','getterB','getterC']) }
//mutation-types.js export const MUTATION_A = 'MUTATION_A'; //mutations.js import { MUTATION_A } from './mutation-types'; export default { [MUTATION_A](state,payload){ state.dataA = payload; } }
//actions.js import { MUTATION_A } from './mutation-types'; //解构赋值前,context是一个对象 export default { actionA(context, payload){ context.commit(MUTATION_A, payload); } } //解构赋值后 export default { actionA({commit, state}, payload){ commit(MUTATION_A, payload); } }
commit = context.commit,为什么这样解构赋值?查看原理。
2、父组件给子组件传递
3、子组件给父组件传递
4、兄弟组件相互传递