vuex 源码分析_vuex源码解析及简单实现

vuex源码解析

一、vuex的使用回顾

//store/index.js

import Vuex from "vuex"

import Vue from "vue"

Vue.use(Vuex)

const store = new Vuex.Store({

state: {

count: 0

}

getters: {

getCount: (state) => {return state.count}

},

mutations: {

changeCount(state, payload) {

state.count = payload

},

},

actions: {

addCount({commit},payload) {

commit("changeCount",payload)

}

}

})

export default store

//main.js

import store from "./store"

new Vue({

el: "#app",

store

})

二、逐句剖析vuex的使用

1. vue.use( )

import Vue from 'vue'

import Vuex from 'vuex'

Vue.use(Vuex)

解析: 上文中的 Vue.use(Vuex)会自动调用Vuex这个对象的install方法, 并在install中传入 Vue 实例,来保证内外的Vue实例一致。你可以把Vue.use方法理解为:Vue.use = ( object ) => { object.install( this )}

思考:故我们重构的 vuex 需要对外暴露一个install 方法

2. new Vuex.Store( )

const store = new Vuex.Store({

state: {...},

getters: {...},

mutations: {...},

actions: {...}

})

解析: 从new Vuex.Store()可以看出导入的Vuex包含着一个名为 Store的构造函数。

思考:综合以上两点,我们可以推断出在 vuex 文件的导出内容大致为:

export default {

install: (vue)=> {

//todo

},

Store: ({state,getters,actions,mutations})=> {

//vuex的核心代码

}

}

3. action

const store = new Vuex.Store({

actions: {

addCount({commit},payload) {

commit("changeCount",payload)

}

}

state:{...},

mutations: {...},

getters: {...}

}

解析: 这种是官方推荐的结构写法,你也可以这么写

addCount(context,payload) {

context.commit("changeCount",payload)

}

解析: 第二种写法种的参数context是指上下文环境即这个store实例。上文中的第一种写法,既然可以从这个context中解构出commit方法,不难得出这个store实例包含commit方法

三、刻画vuex 的大致结构

class Store {

constructor({state, getters, mutations, actions}) {

//todo

}

}

function install(vue){

//todo

}

export default {

Store,

install

}

四、完成 install 方法

思考: 在使用官方的vuex后, 我们在每个组件中都可以访问到this.$store, 可是我们在main.js中只是把store挂载到根实例中,按理说只有在根实例中才可以访问到store

//main.js

import store from "./store"

new Vue({

el: "#app",

store

})

结论: 要在根实例中把store 赋值给$store,并且利用vue组件加载的先父后子原则,从根实例的子组件开始,每个组件都从父组件拿到$store,并将从父组件拿到的$store 赋值给自己的$store属性,从而实现每个组件都拥有$store属性,并且都指向同一个store实例

let Vue

let install = (_Vue) => {

Vue = _Vue

// 通过混入beforeCreate生命周期的钩子函数,使每个vue组件都挂载上store

Vue.mixin({

beforeCreate(){

//this指向每个执行的 vue 组件

//先判断当前的this是不是根实例,因为第一次执行只有根实例上的$options有store实例

if(this.$options.store){

//根实例

this.$store = this.$options.store

} else{

//所以从根实例为一级组件开始,二级组件可以通过this.$parent

//拿到一级组件的store, 然后挂载到自己身上的$store

//如此反复 每个组件都挂载上 $store

this.$store = this.$parent && this.$parent.$store

}

}

})

}

export default install

五、完成 Store 中的 state

思考: store 中 state 的响应式是利用vue中data的响应式来实现的

import install from './intsall.js'

class Store {

constructor({state,getters,mutations,actions}){

this.vm = new Vue ({

data: {

state

}

})

}

}

export default {

install,

Store

}

六、完成 Store 中的 getters

提示: 为了方便读者理解,接下来的内容我们会先列出用法,再展示功能实现代码

getters: {

getCount: (state) => {return state.count}

},

提示: 功能实现代码如下:

class Store {

/***** state code *****/

constructor({state,getters,mutations,actions}){

this.vm = new Vue ({

data: {

state

}

})

}

/***** getters code ****/

this.getters = {}

for(let getterName in getters){

// 利用Object.deineProperty 对this.getter 进行访问劫持

Object.defineProperty(this.getters,getterName,{

get: ()=>{

//getter.getCount = (state) => {return state.count}

return getter[getterName](this.vm.state)

}

})

}

}

七、完成 Store 中的 mutations

提示: 原生使用语法如下:

mutations: {

changeCount(state, payload) {

state.count = payload

},

},

提示: 功能实现代码如下:

class Store {

/***** state code *****/

constructor({state,getters,mutations,actions}){

this.vm = new Vue ({

data: {

state

}

})

}

/***** mutations code ****/

this.mutations = {}

Object.keys(mutations).forEach( mutationName => {

this.mutations[mutationName] = (newValue)=> {

mutation[mutationName](this.vm.state,newValue)

}

})

}

八、完成 Store 中的 commit

提示: 原生使用语法如下:

addCount({commit},payload) {

commit("changeCount",payload)

}

提示: 功能实现代码如下:

class Store {

/***** state code *****/

constructor({state,getters,mutations,actions}){

this.vm = new Vue ({

data: {

state

}

})

}

/***** commit code ****/

this.commit = (mutationName,newValue)=> {

this.mutations[mutationName](newValue)

}

}

九、完成 Store 中的 actions

提示: 原生使用语法如下:

actions:{

addCount(context,payload) {

context.commit("changeCount",payload)

}

}

提示: 功能实现代码如下:

class Store {

/***** state code *****/

constructor({state,getters,mutations,actions}){

this.vm = new Vue ({

data: {

state

}

})

}

/***** actions code ****/

this.actions = {}

Object.keys(actions).forEach(actionName => {

this.actions[actionName] = (newValue)=> {

actions[actionName](this, newValue)

}

})

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值