Vue-手写Vuex

1、原生Vuex

  1. 引入Vuex
import Vuex from 'vuex'
Vue.use(Vuex)
  1. 使用
// store/index.js
export default new Vuex.Store({
  state: {
    // 版本
    version: 'v1'
  },
  getters: {
    version: state => state.version
  },
  actions: {
    setVersion({ commit, state }, params) {
      return new Promise((resolve, reject) => {
        commit('SET_VERSION', params)
        resolve()
      })
    }
  },
  mutations: {
    SET_VERSION(state, params) {
      state.version = params
    }
  }
})


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

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

// xxx.vue
<template>
  <div class="home">
    {{ this.$store.getters.version }}
  </div>
</template>

<script>
mounted() {
    setTimeout(() => {
      this.change();
    }, 1000);
  },

  methods: {
    change() {
      this.$store.dispatch("setVersion", "v2");
    },
  },
</script>

2、手写Vuex

  1. 从原生Vuex引入来看,Vue.use(Vuex)使用use挂载到Vue的实例上,use方法调用vuex的install方法,先来实现install函数
// Vuex.js
const install = (_Vue) => {
    Vue = _Vue
    Vue.mixin({
        beforeCreate() {
            // 每个组件添加store:this.$store调用Store实例
            // 在所有组件中用this.$store都可以获取到Vuex的Store实例
            const options = this.$options
            if (options && options.store) {
                Vue.prototype.$store = typeof options.store === 'function'
                    ? options.store()
                    : options.store;
            } else if (options.parent && options.parent.$store) {
                Vue.prototype.$store = options.parent.$store;
            }
        }
    })
}
  1. Store类
    在原生Vuex中使用new Vuex.Store创建Store对象实例,所以在自定义Vuex文件中增加Store类,并通过实现构造函数来进行属性处理
// Vuex.js
class Store {
	// 构造函数传参
    constructor(options) {
        // 将state属性进行响应式处理
        this._vm = new Vue({
            data: {
                state: options.state
            }
        })

        // getters
        const getters = options.getters || {}
        this.getters = {}
        // 遍历getters的key,把对应的key注册到this.getters对象中,返回key对应的getters中方法的执行结果,并传入state
        Object.keys(getters).forEach(getterName => {
            Object.defineProperty(this.getters, getterName, {
                get: () => {
                    return getters[getterName](this.state)
                },
                enumerable: true
            })
        })

        // 同步
        const mutations = options.mutations || {};
        this._mutations = {};
        // 遍历mutations,实现内部_mutations方法集
        Object.keys(mutations).forEach(mutationName => {
            this._mutations[mutationName] = payload => {
                mutations[mutationName](this.state, payload)
            }
        })

        // 异步
        const actions = options.actions || {};
        this._actions = {};
        // 遍历actions,实现内部_actions方法集
        Object.keys(actions).forEach(mutationName => {
            this._actions[mutationName] = payload => {
                // 第一个参数是context,里面包含我们需要的state,commit等
                actions[mutationName](this, payload)
            }
        })

    }

    // 提供外部使用
    get state() {
        return this._vm.state
    }

    // 使用箭头函数避免this指向问题
    // 在commit方法中获取_mutations
    // 接收两个参数,第一个参数是name,方法名称,第二个参数是payload,调用方法的参数
    commit = (name, payload) => {
        console.log(this)
        this._mutations[name](payload)
    }

    // 使用箭头函数避免this指向问题
    // 在dispatch方法中获取_actions
    // 接收两个参数,第一个参数是name,方法名称,第二个参数是payload,调用方法的参数
    dispatch = (name, payload) => {
        console.log(this)
        this._actions[name](payload)
    }
}
  1. 使用
    将原生Vuex引入方式改成自定义Vuex路径即可实现效果
import Vuex from './Vuex';
Vue.use(Vuex)

如有疑问或不足之处,欢迎交流指正

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值