vuex那些事儿

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的办法,仅供参考。

vuex

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']) }

C、对象属性名用常量表达式

//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;
  }
}

D、对象参数的解构赋值

//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、兄弟组件相互传递

原文地址:https://www.cnblogs.com/camille666/p/vuex.html