手写简版Vuex

222 阅读1分钟

image.png

特点

集中式存储 可预测 单向数据流

1、可存储组件的共同状态 统一的状态管理 2、改状态 通过commit一个mutation函数 改变响应式的状态会通知组件更新 即数据响应式 3、actions异步操作 4、state为状态、store为容器

安装

vue add vuex

[main.js]
import store from './store' 

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

import Vue from 'vue'
import Vuex fom 'my-vuex'

Vue.use(Vuex)

export default new Vuex.Store({
    //响应式的对象
    state:{
        counter:0 
    },
    mutations:{
        add(state){
           state.counter++ 
        }
    },
    //上下文和mutations不同
    actions:{
        add({commit,dispatch,state,root}){
            setTimeout(()=>{
                commit('add')
            },1000)
        }
    }
})
[页面文件]
<template>
    {{$store.state.counte}}
    <p @click="$store.commit('add')"></p>
     <p @click="$store.dispatch('add')"></p>
</template>

实现全局插件store

维持state

实现commit()

实现dispatch()

[my-vuex.js]

class Store{
    constructor(options){
        this.$options = options
        this._mutations = options.mutations
        this._actions = options.actions
        
        //state做响应式处理 会代理直接访问到data中的值
        this._vm = new Vue({
            data(){
                //隐藏一下 不让直接修改值
                return {
                    $$state: optinos.state
                }
            }
        })
        // 直接return options.state的话 ,this.state.counter++ 直接运行,要通过commit执行
        
        //绑定上下文
        this.commit = this.commit.bind(this)
        this.dispatch = this.dispatch.bind(this)
    }
    
    //存取器
    get state(){
        return this._vm._data.$$state
    }
    set state(v){
        console.error('请使用replaceState修改状态')
    }
    
    //commit('add')
    commit(type,payload){
       //匹配type对应的mutation
        const entry = this._mutations[type]
        if(!entry){console.err('error');return}
        entry(this.state,payload)   
    }
    
    //
     dispatch(type,payload){
       //匹配type对应的mutation
        const entry = this._actions[type]
        if(!entry){console.err('error');return}
        //上下文{commit ,dispatch,state}
        return entry(this,payload)   
    }
}

//过渡一下 存储,打包不会把Vue打包进去
let Vue

function install(_Vue){
    Vue = _Vue
    
    //注册$store 在混入中使用  将来执行
    Vue.mixin({
        beforeCreate(){
            //只在根实例中实现
            if(this.$options.store){
                Vue.prototype.$store = this.$options.store
            }
        }
    })
}

//导出vuex
export default {Store,install}