vuex状态管理(一)实现原理

vuex实现源码:
1、维护状态state
2、修改状态commit
3、业务逻辑控制dispatch
4、状态派发getters
5、实现state响应式
6、插件
7、混入

vux实现源码
kvuex.js:

let Vue;
//安装插件
function install(_Vue, storeNamr = "$store") {
    Vue = _Vue;
    //混入目的:把store选项指定到Vue原型上
    Vue.mixin({
        beforeCreate() {
            if (this.$options.store) {
                Vue.prototype.$store = this.$options.store;
            }
        }
    })
}

class Store {
    constructor(options = {}) {
        //new Vue : 利用vue数据响应式
        this.state = new Vue({
            data: options.state
        });
        //初始化mutations
        this.mutations = options.mutations || {};
        this.actions = options.actions || {};
        //getters配置项
        console.log('options', options)
        options.getters && this.handleGetters(options.getters);
    }
    //触发motations,实现commit
    commit = (type, arg) => {
        // this指向store实例
        // this.mutations[type] 获取变更方法
        this.mutations[type](this.state, arg);
    }
    dispatch(type, arg) {
        const fn = this.actions[type];
        fn({
            commit: this.commit,
            state: this.state
        },
            arg
        )
    }
    //{getters:{score(state){return state.xx}}}
    handleGetters(getters) {
        console.log('getters', getters)
        //getters是用户传递的对应规则
        //this.getters是用户最终的值对象
        this.getters = {}; //store实例上的getters
        //Object.keys(getters) 将对象变成数组进行遍历
        //定义只读属性
        Object.keys(getters).forEach(key => {
            Object.defineProperty(this.getters, key, {
                //defineProperties 第三个参数是描述符,get函数只读
                get: () => {
                    return getters[key](this.state);
                }
            })
        })
    }
}
export default { Store, install }

使用kvue
store/kindex.js

import Vue from "vue";
import KVuex from './kvuex';

Vue.use(KVuex)
//这里导出store的实例,又把store混入mixin Vue原型里,
//所以在页面上可以通过 this.$store[store实例]
export default new KVuex.Store({
    state: {
        count: 0
    },
    mutations: {
        increment(state, n = 1) {
            state.count += n;
        }
    },
    //派生用法
    getters: {
        score() {
            return '99999'
        }
    },
    //actions做复杂的业务,类似controller
    actions: {
        //比如ajax请求
        //commit,state上下文数据值
        asynAdd({ commit }, n = 1) {
            console.log('commit', commit)
            return new Promise(resolve => {
                setTimeout(() => {
                    commit('increment');
                    resolve({ ok: 1 })
                }, 1000);
            })

        }
    }
})

//main.js

```bash
import store from './store/kindex'

//指定路由器 store
new Vue({
  store,
  render: h => h(App)
}).$mount('#app')
页面使用

```bash

```bash
<template>
  <div id="app">
    <div>记录数据:{{$store.state.count}}</div>
    <div>派生数据score:{{$store.getters.score}}</div>
    <button @click="add">add</button>
    <button @click="asynAdd">asynAdd</button>
  </div>
</template>

<script>
export default {
  methods: {
    add() {
      this.$store.commit("increment");
    },
    async asynAdd() {
      const res = await this.$store.dispatch("asynAdd");
      console.log("res", res);
    }
  }
};
</script>

发布了18 篇原创文章 · 获赞 0 · 访问量 357

猜你喜欢

转载自blog.csdn.net/weixin_39788999/article/details/104289678
今日推荐