前端大杂烩

面试不要怕,最清晰简洁的手写Vuex,保证有眼睛就能看懂

2021-04-23  本文已影响0人  写写而已
GIF 2021-4-23 22-46-17.gif

开始

MyVuex.js源码,这里为了避免和已经导入Vuex的项目冲突,所以名字有区别

let instance = null
class Mvx {
    store = {
        state: null
    }
    constructor(Vue) {
        const that = this
        this.store.state = new Vue({
            data() {
                return {
                    name: 12
                }
            }
        })
        this.store.commit = {
            SET_NAME(value) {
                that.store.state.name = that.store.state.name + value
            },
            ASYNC_SET_NAME(value) {
                return new Promise(resolve => {
                    setTimeout(() => {
                        that.store.state.name = that.store.state.name + value
                        resolve(that.store.state.name)
                    }, 1000)
                })
            }
        }
        /* 或者用Vue.prototype.$mstore = store,混入的形式是挂在实例上,prototype是在原型上,混入的化感觉性能更好 */
        Vue.mixin({
            beforeCreate() {
                this.$mstore = that.store
            }
        })
    }
}

export const mapStates = (status) => {
    let state = {}
    status.forEach(s => {
        state[s] = () => instance.store.state[s]
    })
    return state
}
export const mapActions = (actions) => {
    let action = {}
    actions.forEach(a => {
        action[a] = instance.store.commit[a]
    })
    return action
}
export default {
    install(Vue) {
        instance = new Mvx(Vue)
        return instance
    }
}

如何使用?

在main.js内导入我的Vuex

import Mvx from './MyVuex'
Vue.use(Mvx)

template模板中,测试从实例直接使用和map state和action之后使用

<template>
    <section class="">
        <p class="fsize fcorg pt10 pb10">
            <span class="fcgreen">$mstore.state.name : </span>{{$mstore.state.name}}
        </p>
        <p class="fsize fcorg pt10 pb10">
            <span class="fcgreen">map name : </span>{{name}}
        </p>
        <el-button @click="changeName" size="small" type="success">change name</el-button>
        <el-button @click="SET_NAME(100)" size="small" type="primary">change name By mapActions</el-button>
        <el-button @click="ASYNC_SET_NAME(10)" size="small" type="warning">By AsyncMapAction</el-button>
    </section>
</template>

在模板中使用

// 导入
import { mapStates, mapActions } from '../MyVuex'
export default {
    name: '/test-my-vuex',
    data() {
        return {}
    },
    computed: {
        /* 通过计算属性,map到data */
        ...mapStates(['name'])
    },
    methods: {
        /* 通过mapActions,map到methods中。测试:1.直接调用,2.异步调用,3.直接通过实例调用 */
        ...mapActions(['SET_NAME', 'ASYNC_SET_NAME']),
        changeName() {
            this.$mstore.commit.SET_NAME(12)
        }
    }
}

推介一下自己的基于Vue2.6的兰陵王框架https://lanling.diumx.com 和 基于Vue3+Ts+Vite的花木兰框架http://mulan.diumx.com

上一篇下一篇

猜你喜欢

热点阅读