vuex

vuex-集中式管理数据

vuex官网:https://vuex.vuejs.org/zh-cn/

一、安装

cnpm install vuex --save-dev

二、vuex数据流示意图

三、使用vuex

import Vuex from 'vuex';
Vue.use(Vuex);
// 创建store实例 const store = new Vuex.Store({ // 存储state状态值   state: {
    ...
  },
// 类似于事件集合,每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数,是同步函数   mutations: {
    ...
  },
// 更改store状态的唯一方法是提交mutation,mutation已经对状态进行更改,actions就是用来提交mutation的,可以包含任意异步操作。   actions: {
    ...
  },
// 被认为是store的计算属性,getters接受state作为第一个参数   getters: {
    ...
  } })
/* eslint-disable no-new */ new Vue({ // 使用store,将store实例注入到根组件下的所有子组件中 // 子组件可以通过this.$store来访问store对象 store // store:store (key:value,key和value名字相同时,可省略value) })

四、核心概念

1、state

state负责存储所有的状态数据,可以直接用 this.$store.state 获取store的状态数据。

html:
   <div>count: {{ count }}</div>
 
script:
// 创建store实例
const store = new Vuex.Store({
    state:{
        count:0
    }
})

export default{
    computed:{
        count(){
             return this.$store.state.count;
        }
    }
};

结果--> count:0

也可以使用 mapState辅助函数 将state映射到计算属性中去。

// 在单独构建的版本中辅助函数为 Vuex.mapState
import { mapState } from 'vuex'

export default {
  // ...
  computed: mapState({
    // 映射 this.count 为 store.state.count
    count: state => state.count
  })
}

2、getters

getters被认为是store的计算属性,接受state作为第一个参数,对state进行二次加工,通过 this.$store.getters 访问。

html:
   <div>用户名: {{ userName }}</div>

script:
// 创建store实例
const store = new Vuex.Store({
    state:{
        name:'Jack'
    },
    getters:{  // 被认为是store的计算属性,对state数据进行二次处理,从而被其他地方进行调用
        userName(state){
            return state.name + ',Hello';
        }
    }
})

export default{
    computed:{
        userName(){
            return this.$store.getters.userName;
        }
    }
};

 结果--->  用户名: Jack,Hello

mapGetters 辅助函数 仅仅是将store中的getter映射到局部计算属性。

import { mapGetters } from 'vuex'

export default {
  // ...
  computed: {
  // 使用对象展开运算符将 getter 混入 computed 对象中
    ...mapGetters([
      // 映射 `this.doneTodosCount` 为 `store.getters.doneTodosCount`
      'doneTodosCount',// ...
    ])
  }
}

3、mutations

mutations类似于事件,更改store状态的事件函数,是改变状态的唯一方法,每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数。只能是同步的。

<div>数量: {{ count }}</div>

export default{
    computed:{
        name(){
            return this.$store.state.count;
        }
    }
}

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment (state) {
      // 变更状态
      state.count++
    }
  }
})

mutation更改了store 状态,并不代表更改成功,需要提交才能触发mutation的方法。

在组件中提交mutation,你可以在组件中使用 this.$store.commit('xxx') 提交 mutation,或者使用 mapMutations 辅助函数将组件中的 methods 映射为 store.commit 调用。

<a href="javascript:;" @click="click">点击</a>
export default {
  methods: {
    click() {
      this.$store.commit('increment');
    }
  }
}
import { mapMutations } from 'vuex'

export default {
  // ...
  methods: mapMutations([
      'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')`
    ])
}

<button @click="increment">点击</button>

4、actions

actions类似于mutations,用于改变状态,不过不同的是通过提交mutations来触发mutations改变store状态,可以包含任意异步操作。

<div>数量: {{ count }}</div>
<div>用户名: {{ name }}</div>

const store = new Vuex.Store({
   state:{
        count:0,
        name:'Jack'
    },
    mutations:{   // 改变状态的唯一方法,但也要提交才有用
        increment(state){
            state.count++;
        },
        updateName(state,userName){  // 也可接受第二个参数
            state.name = userName;
        }
    },
    actions:{  // 提交mutations
        incrementAction(context){  // 提交increment,代替method的add点击事件中的this.$store.commit('increment');
            context.commit('increment');
        },
        updateNameAction(context,userName){  // 提交updateName
            context.commit('updateName',userName);
        }
    }
})

export default{
    computed:{
        count(){
            return this.$store.state.count;
        },
        name(){
            return this.$store.state.name;
        }
    }
}

actions通过 this.$store.dispatch('increment') 来触发,或者通过辅助函数 mapActions (与mapMutations类似) 将组件的 methods 映射为 store.dispatch 调用。

<a href="javascript:;" @click="add">点击</a>

export default{
    methods:{
        add(){
            // this.$store.commit('increment');  // 提交increment事件类型来触发mutations,实现count++
            // this.$store.commit('updateName','Tom'); // 用户名变成Tom
            
            // vuex中定义了actions提交mutations,这里就不需要提交mutations来触发事件了,只要触发actions就行
            this.$store.dispatch('incrementAction');
            this.$store.dispatch('updateNameAction','Tom');
        }
    }
}
import {mapActions} from 'vuex'

export default {
  methods: mapActions([
    'increment',   // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`
  ])
}

<button @click="increment">点击</button>

五、demo实例

demo下载地址:https://github.com/ccyinghua/vuex-demo

1、简易vuex

main.js

import store from './store.js'

//挂到Vue实例身上
new Vue({
    store,
    el: '#app',
        render: h => h(App)
})

App.vue

import {mapGetters,mapActions} from 'vuex'       

export default{
        computed:mapGetters([  
            'count',
            'getOdd'
        ]),
        methods:mapActions([
            'increment',
            'decrement',
            'clickOdd',
            'clickAsync'
        ])
}

//store.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex);

var state = {
    count:10
}

const mutations = {
    increment(state){       //事件;处理状态(数据)变化;  
        state.count++;
    },
    decrement(state){
        state.count--;
    }
}

const actions = {
        increment: ({          // 提交mutations
                commit
        }) => {
                commit('increment')
        },
        decrement: ({
                commit
        }) => {
                commit('decrement')
        },
        clickOdd: ({
                commit,
                state
        }) => {
                if(state.count % 2 == 0){
                    commit('increment')
                }
        },
        clickAsync: ({
                commit
        }) => {
                new Promise((resolve) => {
                    setTimeout(function(){
                        commit('increment');
                        resolve();
                    },1000)
                })
        }
}

const getters = {
    count(state){
        return state.count;
    },
    getOdd(state){
        return state.count % 2 == 0 ? '偶数' : '奇数';
    }
}

//需要导出Store对象
export default new Vuex.Store({
        state,
        mutations,
        actions,
        getters
})

2、复杂vuex

main.js

import store from './store/'

//挂到Vue实例身上
new Vue({
    store,
    el: '#app',
    render: h => h(App)
})

App.vue

import {mapGetters,mapActions} from 'vuex'

export default{
    computed:mapGetters([
        'count',
        'getOdd'
    ]),
    methods:mapActions([
        'increment',
        'decrement',
        'clickOdd',
        'clickAsync'
    ])
}

store文件夹--index.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex);

import mutations from './mutations'
import actions from './actions'

//需要导出Store对象
export default new Vuex.Store({
    modules:{
        mutations
    },
    actions
})

store文件夹-types.js

// 使用常量替代 Mutation 事件类型,详见官网
export const INCREMENT = 'INCREMENT';

export const DECREMENT = 'DECREMENT';

store文件夹-getters.js

export default{
    count: (state) => {
        return state.count;
    },
    getOdd: (state) => {
        return state.count % 2 == 0 ? '偶数' : '奇数'
    }
}

store文件夹-mutations.js

import {
    INCREMENT,
    DECREMENT
} from './types'
import getters from './getters'

const state = {
    count:20
}

const mutations = {
    [INCREMENT](state){
        state.count++;
    },
    [DECREMENT](state){
        state.count--;
    }
}

export default{
    state,
    mutations,
    getters
}

store文件夹-actions.js

import * as types from './types'

export default{
    increment: ({
        commit
    }) => {
        commit(types.INCREMENT)
    },
    decrement: ({
        commit
    }) => {
        commit(types.DECREMENT)
    },
    clickOdd: ({
        commit,
        state
    }) => {
        if(state.mutations.count % 2 == 0){
            commit(types.INCREMENT)
        }
    },
    clickAsync: ({
        commit
    }) => {
        new Promise((resolve) => {
            setTimeout(function(){
                commit(types.INCREMENT);
            },1000)
        })
    }
}
原文地址:https://www.cnblogs.com/ccyinghua/p/7865804.html