VUEX

137 阅读2分钟

案例参考链接

(一)VUEX里面的属性有:

image.png

属性解释
state存储数据的
获取数据最好推荐使用getters
硬要使用的话可以用MapState, 先引用,放在compute中...mapState(['方法名','方法名'])
getters获取数据的:this.$store.getters.xxx
也可使用mapGetters 先引用,放在compute中,...mapGetters(['方法名','方法名'])
mutations同步操作数据的:this.$store.commit(“方法名”,数据)
也可使用mapMutations ,使用方法和以上一样
actions异步操作数据的:this.$store.dispatch(“方法名”,数据)
也可使用mapActions ,使用方法和以上一样
modules板块,里面可以放多个vuex
  • 我们使⽤state定义数据,
  • 使⽤mutation定义修改数据的逻辑,并且在组件中使⽤commit去调⽤mutations。
  • 在此基础之上,还可以⽤getters去实现Vuex世界的计算属性,
  • 使⽤action来去定义异步任务,并且在内部调⽤mutation去同步数据。

(二)实现原理(vue3版)

代码git地址

// mini-vuex.js
import { inject, reactive, computed } from 'vue';
const STORE_KEY = '__store__';
function useStore() {
    return inject(STORE_KEY);
}
// 暴露createStore去创建Store的实例
function createStore(options) {
    return new Store(options);
}
class Store {
    constructor(options) {
        this.$options = options;
        // Store类内部变量_state存储响应式数据
        this._state = reactive({ data: options.state() }); //获取传入的state,变成响应式
        this._mutations = options.mutations; //获取传入的mutations
        this._actions = options.actions;
        // getters
        this.getters = {};
        Object.keys(options.getters).forEach(name => {
            const fn = options.getters[name]; //获取⽤⼾配置好的getters
            //用computed包裹,将getters的内容变成计算属性
            this.getters[name] = computed(() => fn(this.state));
        });
    }
    // 【state方法实现】:读取state的时候直接获取响应式数据 _state.data
    get state() {
        return this._state.data;
    }
    // 【commit方法实现】:提供commit函数去执⾏⽤⼾配置好的mutations。
    commit = (type, payload) => {
        console.log('【 type, payload 】-30', type, payload);
        // type:commit传入的方法名
        const entry = this._mutations[type]; //获取⽤⼾配置好的mutations
        entry && entry(this.state, payload);
    };
    // 【dispatch方法实现】:提供commit函数去执⾏⽤⼾配置好的mutations。
    dispatch(type, payload) {
        const entry = this._actions[type]; //获取⽤⼾配置好的actions
        return entry && entry(this, payload);
    }
    // 为了让useStore能正常 ⼯作,我们需要给store新增⼀个install⽅法,
    // 这个⽅法会在app.use函数内部执⾏。我们通过app.provide函数注册store给全局的组件使⽤。
    install(app) {
        // provide注册了数据后,所有的⼦组件都可以通过inject获取数据,
        app.provide(STORE_KEY, this);
    }
}
export { createStore, useStore };

使用

import { createStore } from './mini-vuex'
const store = createStore({
    state() {
        return { count: 666 };
    },
    // vuex的计算属性
    getters: {
        double(state) {
            return state.count * 2;
        }
    },
    // mutations:同步修改数据, mutation内部的函数会把state作为参数,
    mutations: {
        add(state) {
            // 我们直接操作state.count就可以完成数据的修改。
            state.count++;
        }
    },
    // mutations:异步修改数据
    actions: {
        // 这个配置中所有的函数,可以通过解构获得 commit函数。
        // 内部的异步任务完成后,就随时可以调⽤commit来执⾏mutations去更新数据。
        asyncAdd({ commit }) {
            setTimeout(() => {
                commit('add'); //可以调⽤commit来执⾏mutations去更新数据。
            }, 1000);
        }
    }
});
export default store;

[ 延伸问题 ]

1. vuex中 this.$store.dispatch()this.$store.commit()方法的区别?

区别主要是存取方式的不同,两个方法都是传值给vuex的mutation改变state,可以不走dispatch ,直接commit到mutations

  • this.$store.dispatch() :异步操作
    • 写法:this.$store.dispatch('action方法名',值)
    • 含有异步操作,在actions方法里面通过commit调用mutation中的方法,把值赋给state中的字段
  • this.$store.commit():同步操作
    • 写法:this.$store.commit(‘mutations方法名’,值)
    • 直接提交commit修改state中的值