当前位置: 首页 > Web前端 > vue.js

Vuex源码分析

时间:2023-03-31 15:00:27 vue.js

1.vuex使用回顾//store/index.jsimportVuexfrom"vuex"importVuefrom"vue"Vue.use(Vuex)conststore=newVuex.Store({state:{count:0}getters:{getCount:(state)=>{returnstate.count}},mutations:{changeCount(state,payload){state.count=payload}, },actions:{addCount({commit},payload){    commit("changeCount",payload)}}})exportdefaultstore//main.jsimportstorefrom"./store"newVue({el:"#app",store})二。逐句分析vuex的使用1.vue.use()importVuefrom'vue'importVuexfrom'vuex'Vue.use(Vuex)分析:上面的Vue.use(Vuex)会自动调用vuex的installobject方法,并在install中传入vue实例,保证内外vue实例一致。Vue.use方法可以理解为:Vue.use=(object)=>{object.install(this)}思路:因此,我们重构后的vuex需要对外暴露一个install方法2.newVuex.Store()conststore=newVuex.Store({  state:{...},  getters:{...},  mutations:{...},  actions:{...}})分析:从newVuex.Store()中,我们可以看到导入的Vuex包含一个名为Store的构造函数。思考:根据以上两点,我们可以推断出vuex文件的导出内容大致为:exportdefault{install:(vue)=>{//todo},Store:({state,getters,actions,mutations})=>{  //vuex核心代码  }}3.actionconststore=newVuex.Store({actions:{addCount({commit},payload){    commit("changeCount",payload)}}state:{...},mutations:{...},getters:{...}}分析:这是官方推荐的结构,也可以这样写addCount(context,payload){  context.commit("changeCount",payload)}分析:第二种写法的参数context指的是context环境,也就是store实例上面的第一种写法,因为commit方法可以从这个context中解构出来,不难发现这个store实例包含commit方法3.描述vuexvue的大致结构{  //todo}exportdefault{  Store,  install}四、思考如何完成安装:使用t后官方vuex,我们可以在每个组件store中访问this.$,但是我们只将store挂载到main.js中的根实例。按理说只有根实例才能访问store//main.jsimportstorefrom"./store"newVue({el:"#app",store})结论:将store赋值给根实例中的$store,利用Vue组件先父子加载的原则,从根实例的子组件开始,每个组件从父组件获取$store,并将父组件的$store赋值给自己的$storeattributes,这样每个组件都有一个$store属性,都指向同一个store实例letVueletinstall=(_Vue)=>{Vue=_Vue  //通过混入beforeCreate生命周期的钩子函数,每个Vue组件都挂载在store上Vue.mixin({beforeCreate(){       //this指向每一个被执行的vue组件       //先判断当前this是否为根实例,因为先执行只有根实例上的$options有存储实例if(this.$options.store){          //根实例          this.$store=this.$options.store}else{         //sofrom根实例从一级组件开始,二级组件可以通过this.$parent获取一级组件的store         //然后将它挂载到它自己的$store         //等等每个组件Mount$storethis.$store=this.$parent&&this.$parent.$store}}})}exportdefaultinstall5.完成Store中state的思考:store中state的响应是使用Vue中的数据importinstallfrom'./intsall.js'classStore{constructor({state,getters,mutations,actions}){this.state=newVue({data:state})        }}exportdefault{install,Store}6.完成Store中的getterTips:为了方便读者,在下面的内容中,我们将首先列出用法,然后展示函数实现代码getters:{getCount:(state)=>{returnstate.count}},提示:函数实现代码如下:classStore{/*****状态代码*****/constructor({state,getters,mutations,actions}){this.state=newVue({data:state})  }    /*****getters代码****/    this.getters={}  for(letgetterNameingetters){  //使用Object.deineProperty劫持对this.getter的访问  Object.defineProperty(this.getters,getterName,{get:()=>{      //getter.getCount=(state)=>{returnstate.count}        returngetter[getterName](this.vm.state)      }    })  }}7.在Store中完成mutationsTips:原生使用语法如下:mutations:{changeCount(state,payload){state.count=payload},},Tips:函数实现代码如下:classStore{/*****statecode*****/constructor({state,getters,mutations,actions}){this.state=newVue({data:state})  }    /******突变代码****/  this.mutations={}  Object.keys(mutations).forEach(mutationName=>{    this.mutations[mutationName]=(newValue)=>{      mutation[mutationName](this.vm.state,newValue)    }  })}8.完成Store中的commit提示:原生使用语法如下:addCount({commit},payload){commit("changeCount",payload)}提示:函数实现代码如下:classStore{/*****statecode*****/constructor({state,getters,mutations,actions}){this...[mutationName](newValue)  }}9.完成Store中的actions提示:原生使用语法如下:actions:{addCount(context,payload){  context.commit("changeCount",payload)}}提示:函数实现代码如下:classStore{/*****statecode*****/constructor({state,getters,mutations,actions}){this.state=newVue({data:state})  }    /****动作代码****/  this.actions={}  Object.keys(actions).forEach(actionName=>{    this.actions[actionName]=(newValue)=>{      actions[actionName](this,newValue)    }})}