Skip to content

搭建 Vuex 环境

安装

sh
npm i vuex@3 // Vue2

创建 store

创建 src/store/index.js 文件,这个文件用于创建 Vuex 中最核心的 store

javascript
// 引入 Vue
import Vue from 'vue'

// 引入 Vuex
import Vuex from 'vuex';

// 使用 Vuex 插件
Vue.use(Vuex)

// 准备 actions 处理相应组件中的动作。
const actions = {};

// 准备 mutations 加工数据。
const mutations = {};

// 准备 state 存储数据。
const state = {};

// 创建并暴露 store
export default new Vuex.Store({
    actions,mutations,state
})

引入 store

main.js 文件中引入并使用 store

javascript
import Vue from 'vue'
import App from './App.vue'
import store from './store'

Vue.config.productionTip = false;

new Vue({
  render: h => h(App),
  store
}).$mount('#app')

使用 store

store 组成部分

  1. Actions:服务员,在它身上可以做一些逻辑处理,例如发起 Ajax 请求等。

  2. Mutations:厨师,真正操作数据的那个人。

  3. State:存储器,存放数据。

  4. 以上三者在 src/store/index.js 文件中已经配置了。

API

  1. dispath:检测 VC 的动作,并将动作传递给 Actions。他需要两个参数,一是动作名称,二是动作携带的数据。
  2. commit:在 VC 和 Actions 中都可以调用 commit,如果在 VC 上调,则不经过 Actions 这一步,也就意味着没有其他逻辑。

求和案例

Count.vue

Vue
<template>
    <div>
        <h1>当前计算的值为: {{$store.state.sum}}</h1>
        <select v-model.number="num">
            <option value="1">1</option>
            <option value="2">2</option>
            <option value="3">3</option>
        </select>
        <button @click="inc">+</button>
        <button @click="dec">-</button>
        <button @click="incOdd">奇数加法</button>
        <button @click="incWeit">延迟加法</button>
    </div>
</template>

<script>
    export default {
        name: 'Count',
        data() {
            return {
                num: 1
            };
        },
        methods: {
            inc(){
                this.$store.commit('INC',this.num);
            },
            dec(){
                this.$store.commit('DEC',this.num);
            },
            incOdd(){
                this.$store.dispatch('incOdd', this.num);
            },
            incWeit(){
                this.$store.dispatch('incWeit', this.num);
            },
        },
        mounted() {
            console.log(this);
        },
    };
</script>

index.js

javascript
// 引入 Vue
import Vue from 'vue'

// 引入 Vuex
import Vuex from 'vuex';

// 使用 Vuex 插件
Vue.use(Vuex)

// 准备 actions 用于相应组件中的动作。
const actions = {
    incOdd(context,value){
        if(context.state.sum % 2) context.commit('INC',value);
    },
    incWeit(context,value){
        setTimeout(() => {
            context.commit('INC',value);
        }, 1000);
    }
};
 
// 准备 mutations 用于操作数据。
const mutations = {
    INC(state,value){
        state.sum += value;
    },
    DEC(state,value){
        state.sum -= value;
    }
};

// 准备 state 用于存储数据。
const state = {
    sum: 0
};

// 创建并暴露 store
export default new Vuex.Store({
    actions,mutations,state
})

getters 配置项

  1. 这个配置项也是配置在 src/store/index.js 文件中的,与 actions、mutations、state 是同级的。

  2. 它的作用有点类似于组件里的 computed 计算属性,也需要用 return 返回一些计算结果。

  3. 配置成功后,需要向外暴露

    javascript
    // getters 配置项
    const getters = {
        bigSum(state){
            return state.sum * 10
        }
    }
    
    // 创建并暴露 store
    export default new Vuex.Store({
        actions,mutations,state,getters
    })
  4. 在组件中,可以通过 $store.getters.bigSum 拿到 bigSum 的值。

代码优化

mapState 与 mapGetters

  1. 使用 mapState 和 mapGetters 的目的是简化代码,通常写在计算属性里。

  2. 代码可以简写为

    Vue
    <template>
        <div>
            <h1>当前计算的值为: {{sum}}</h1>
            <h3>数据放大 10 倍后: {{bigSum}}</h3>
            <h3>昵称: {{nickname}}, 年龄: {{age}}</h3>
            ……
        </div>
    </template>
    
    <script>
        import {mapState,mapGetters} from 'vuex';
    
        export default {
            name: 'Count',
            data() {
                return {
                    num: 1
                };
            },
            computed: {
                ...mapState(['sum','nickname','age']),
                ...mapGetters(['bigSum'])
            },
            ……
        };
    </script>

mapMutations 与 mapActions

  1. mapMutations 与 mapActions 的目的也是简化代码,通常写在事件处理 methods 中。

  2. 代码可以简写为

    Vue
    <template>
        <div>
            ……
            <button @click="inc(num)">+</button>
            <button @click="dec(num)">-</button>
            <button @click="incOdd(num)">奇数加法</button>
            <button @click="incWeit(num)">延迟加法</button>
        </div>
    </template>
    
    <script>
        import {mapState,mapGetters,mapMutations,mapActions} from 'vuex';
    
        export default {
            name: 'Count',
            data() {
                return {
                    num: 1
                };
            },
            ……
            methods: {
                ...mapMutations({inc:'INC',dec: 'DEC'}),
                ...mapActions(['incOdd','incWeit']),
            },
        };
    </script>

模块化开发

基本用法

  1. index.js 文件中,我们分别创建了 actions、mutations、state 并将它们暴露出去,但在实际开发中会对他们三位进行分组,目的是更好的维护代码。

  2. 分组原则:每一类具备一组 actions、mutations、state。

  3. 例:学生与班级

    javascript
    // index.js
    
    // 引入 Vue
    import Vue from 'vue'
    // 引入 Vuex
    import Vuex from 'vuex';
    // 使用 Vuex 插件
    Vue.use(Vuex)
    
    // 学生类
    const Student = {
        namespaced: true,
        actions: {},
        mutations: {},
        state: {}
    }
    
    // 班级类
    const Class = {
        namespaced: true,
        actions: {},
        mutations: {},
        state: {}
    }
    
    // 创建并暴露 store
    export default new Vuex.Store({
        modules: {
            Student,Class
        }
    })
  4. namespaced: true 表示开启命名空间。

  5. modules 导出是模块化导出的固定写法。

  6. 如何使用?

    javascript
    ...mapState('Student',['stuList']), // 获取 Student 的 state 中的数据 stuList
    ……
    ...mapActions('Student',['add']), // 调用 Student 的 Action 中的方法 add

actions 中方法的相互调用

  1. 在模块化开发中,通常会遇到 actions 中的方法互相调用,这是只需要借助第一个形参 con 的 dispatch 方法即可实现。

  2. dispatch 方法共有两个参数,分别是 actions 中的方法名和方法参数

  3. 代码演示

    javascript
    actions: {
        getUserInfo(con){
            con.dispatch('prins',111)
        },
        prins(_,e){
            console.log(e);	// 打印结果 111
        }
    },

基于 MIT 许可发布