Vue源码系列之:Vuex源码简单实现

·  阅读 3336

大家好我是前端菜鸟林三心,今天给大家分享Vuex源码的简单实现。

此次只实现state,getters,mutations,actions。其实vuex的组成就是install方法和store类这两个,而重点就是install里的mixin,这是vuex的核心

这是文件目录

vuex.js

// vuex.js
let Vue;

const install = (v) => {
    console.log(v)
    Vue = v;
    Vue.mixin({
        beforeCreate() {
            if (this.$options && this.$options.store) {
                // root
                this.$store = this.$options.store;
            } else {
                this.$store = this.$parent && this.$parent.$store;
            }
            console.log(this.$store);
        },
    })
}

class Store {
    constructor(options) {
        this.vm = new Vue({
            data: {
                state: options.state
            }
        });

        let getters = options.getters || {};
        this.getters = {};
        console.log(Object.keys(this.getters))
        Object.keys(getters).forEach(getterName => {
            Object.defineProperty(this.getters, getterName, {
                get: () => {
                    return getters[getterName](this.state);
                }
            })
        })

        let mutations = options.mutations || {};
        this.mutations = {};
        Object.keys(mutations).forEach(mutationName => {
            this.mutations[mutationName] = payload => {
                mutations[mutationName](this.state, payload);
            }
        })

        let actions = options.actions || {};
        this.actions = {};
        Object.keys(actions).forEach(actionName => {
            this.actions[actionName] = payload => {
                actions[actionName](this.state, payload);
            }
        })
    }
    get state() {
        return this.vm.state;
    }
    commit(name, payload) {
        this.mutations[name](payload);
    }
    dispatch(name, payload) {
        this.actions[name](payload);
    }
}

export default {
    install,
    Store
}
复制代码

index.js

// index.js
import Vue from 'vue';
import vuex from './vuex';
Vue.use(vuex);


export default new vuex.Store({
    state: {
        num: 1
    },
    getters: {
        getNum(state) {
            return state.num * 2;
        }
    },
    mutations: { in (state, payload) {
            state.num += payload;
        },
        de(state, payload) {
            state.num -= payload;
        }
    },
    actions: { in (state, payload) {
            setTimeout(() => {
                state.num += payload;
            }, 2000)
        }
    }
})
复制代码

main.js

// main.js
import Vue from 'vue';
import App from './App.vue'

import store from './store/index';


new Vue({
    store,
    el: '#app',
    components: {
        App
    },
    template: '<App/>',
})
let linsanxin = 1;
console.log(linsanxin)
复制代码

App.vue

// App.vue
<template>
  <div>
    {{this.$store.state.num}}
    {{this.$store.getters.getNum}}
    <button @click="addNum">呵呵</button>
    <button @click="addNumByAsync">呵呵异步</button>
    <div id="a">asadasd</div>
    <button @click='add'>添加</button>
    <ul v-for="(item,index) in list" :key="index">
      <li class="ll">{{item.name}}</li>
    </ul>
  </div>
</template>

<script>
import img from "./asset/images/haha.jpg";
import "./asset/styles/test.css";
import "./asset/styles/global.stylus";
export default {
  name: "App",
  created() {
    console.log(img);
  },
  data() {
    return {
      list: [
        { name: "lin" },
        { name: "lin" },
        { name: "lin" },
        { name: "lin" },
        { name: "lin" }
      ]
    };
  },
  methods: {
      add(){
          this.list.push({name:'k'})
      },
      addNum(){
        this.$store.commit('in',2);
      },
      addNumByAsync(){
        this.$store.dispatch('in',3);
      }
  },
};
</script>

<style scoped lang='stylus'>
#a {
  background: red;
}
</style>

复制代码

效果

结语:我一定会成为大神的,加油。

分类:
前端
标签:
分类:
前端
标签: