vue-Vuex源码实现

这是我参与更文挑战的第6天,活动详情查看: 更文挑战

注:以下是个人理解、如有不对还望指正!

认识Vuex

Vuex 是一个专为 Vue.js 应用程序开发的 状态管理模式。它采用集中式存储管理应用的所有组件的状态,说白一点一个全局的状态仓库、里面的数据是响应式、可在任意页面使用仓库的变量

这是在Vuex官网拿到一个流程图 文档地址
image.png

正版Vuex的使用

  • 安装
yarn add vuex 
//或
npm install vuex
复制代码
  • 使用

在src新建/store/index.js

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)

const store = new Vuex.Store({
    state:{
        userInfo:{
            name:"张三"
        }
    },
    mutations:{
        setUserInfo(state, data){
            state.userInfo = data
        }
    },
    getters:{
        userInfo: state =>  state.userInfo
    },
    actions:{
        asyncSetUserInfo({ commit },data){
            setTimeout( () =>{
                commit('setUserInfo',data)
            },1000)
        }
    }
})

export default store;
复制代码
  • main.js使用
import Vue from "vue";
import App from "./App.vue";
import store from "./store"
new Vue({
    store,
    render: (h) => h(App),
}).$mount("#app");
复制代码
  • 页面显示
<template>
    <div class="demo">
        {{ $store.getters.userInfo.name }}
        <button @click="$store.dispatch('asyncSetUserInfo',{ name:'李四'})">修改名称</button>
    </div>
</template>
复制代码

更新流程:在组件里面使用dispatch去触发actions、在actions里面使用commit提交在mutations最后在mutations里面去修改store里面的state值

重写Vuex

  • 我们要实现那些呢、通过流程我们知道、我们得有个dispatch方法、commit、等…那我们开始实现把、在store下新建Vuex.js
let Vue;
function install( _Vue ){
    Vue = _Vue;
    //把store选项指定到Vue原型中
    _Vue.mixin({
        beforeCreate(){
            if(this.$options.store){
                //这个store是你new Vuex.store的实例
                //挂载到原型就可以通过this.$store拿到你自己定义在仓库的state和一些方法
                Vue.prototype.$store = this.$options.store;
            }
        }
    })
}

class Store {
    // option 就是你传入的对象里面有state mutations action getters
    constructor( option = {} ){
        //利用vue的响应式
        this.state = new Vue({
            data:option.state
        });
        // 初始化mutations
        this._mutations = option.mutations || {};
        // 初始化action
        this._actions = option.actions || {};
        option.getters && this.handleGetters( option.getters );
        //重写commit方法、并把当前this指向更改到当前实例
        const store = this;
        const { commit } = this;
        this.commit = function boundCommit (type, payload) {
            return commit.call(store, type, payload)
        }
    }
    // 触发mutations commit 定义
    commit( type, arg ){
        //变更函数
        const fn = this._mutations[type];
        fn( this.state, arg )
    }
    // 通过type查找action对象的方法 去执行action方法
    dispatch( type, arg ){
        const fn = this._actions[type];
        fn( { commit:this.commit, state:this.state } , arg)
    }
    // getters
    handleGetters( getter ){
        this.getters = {};
        Object.keys( getter ).forEach( key =>{
            //只设置已读
            Object.defineProperty( this.getters, key,{
                get: ()=>{
                    return getter[key]( this.state )
                }
            })
        })
    }
}
export default { Store, install }
复制代码

然后我们更改store/index.js的vuex文件路径测试下把

import Vuex from "./Vuex"

总结

简易版Vuex整体流程并不难理解、当然正版Vuex可比这复杂了、简易版大概的流程:维护个个类型对象的方法、通过实际传入的方法名去取对应方法执行、最终修改state、一个小细节需要注意下、重重写commit的目的是为了把commit方法作为参数传入给开发者使用、这时候会有一个this指向的问题、所以要重写这么一个操作

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享