4.29 手写 vuex
let Vue class Store{ constructor(options){ // step1 step1注册$store后让页面能正常显示state // this.state = options.state // step2实现mutations actions commit dispatch // step2-01 初步实现mutations actions commit dispatch this._mutations = options.mutations this._actions = options.actions // step2-02 锁死commit和dispatch的this指向 this.commit = this.commit.bind(this) this.dispatch = this.dispatch.bind(this) // step2-03 让state响应 触发render组件重新渲染 // 如何造响应式数据? // 方式1:借鸡生蛋 - new Vue({data: {XXX: '/'}}) // 方式2:Vue.util.defineReactive(obj, 'XXX', '/') // step2-03 让state变成响应式 同时state不可以随意改变 this._vm = new Vue({ data:{ // Vue约定:以 _ 或 $ 开头的属性 不会 被 Vue 实例代理 $$state : options.state } }) } // step2-03 让state变成响应式 同时state不可以随意改变 get state(){ return this._vm._data.$$state } set state(v){ console.error('请使用replaceState重置状态'); } // step2-01 初步实现mutations actions commit dispatch commit(type,payload){ console.log('in commit:',this.state) const mutation = this._mutations[type] if(!mutation){ console.error('mutation不存在') return } mutation(this.state,payload) } dispatch(type,payload){ const action = this._actions[type] if(!action){ console.error('action不存在') return } // 为什么第一个是this,也就是Store,因为action中需要commit,可以在Store拿到 action(this,payload) // 报错 Cannot read property 'state' of undefined // 由于dispatch通常是异步的,所以会异步commit。而commit依赖this.state,但是异步容易丢失上下文,所以我们在constructor中锁死commit和dispatch的this指向 ===》 step2-02 } // OK step2已经完成 但是我们可以发现一个问题 页面上state不会变化,我们需要让Store.state变成响应式数据,触发Vue的render组件渲染 ===》step2-03 } // 入口:install function install(_Vue){ // 保存Vue Vue = _Vue // step1注册$store Vue.mixin({ beforeCreate(){ /** * this.$options用来访问main.js中 new Vue({ render: h => h(App), store, })中的options 这里我们是要拿到store */ if(this.$options.store)Vue.prototype.$store = this.$options.store } }) } export default {Store,install}