vuex

Posted ccyinghua

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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)
        })
    }
}

 

以上是关于vuex的主要内容,如果未能解决你的问题,请参考以下文章

VSCode自定义代码片段13——Vue的状态大管家

项目集成 vue-router 和 vuex

手把手教你学vue-4(vuex)

Vue 教程(四十九)Vuex 核心概念和项目结构

Vue 教程(四十九)Vuex 核心概念和项目结构

Vue 教程(四十九)Vuex 核心概念和项目结构