Open Abiel1024 opened 6 years ago
在项目中一直有用到vuex,觉得vuex是真的好用。十分好奇其中的原理是怎么样的,所以就拿源码,对应着网上的文章进行学习。对应的源码地址: vuex源码
源码分析技巧: 网上推荐的方法都是把源码拷到本地,然后就开始看源码,呃。。。。,反正我看了之后是一脸懵逼。可以将源码拷贝到自己的项目中,通过import的方式去引入他(通常我们通过依赖去引入)。这样的好处就是能在他的代码中修改。在控制台输出,打断点...,结合自己项目的使用情况,你就会发现好理解多了。不然光看代码,你很难分析他传经来的参数到底是什么?就会导致后面的分析都会异常的困难。
src 目录下的文件并不多,module下主要是module的两个构造函数,plugins下面是两个vuex内置插件,还有对应的几个js,整个源码加起来1000行差不多吧(看去年的文章还只有500-600行),虽然量也不是特别大,但是想要完全看明白还是需要花一点时间的。
看源码一般是从入口开始,因为我们用的时候也是会通过import的方式去引入。所以入口文件就相当于是桥梁,通过入口文件,去了解插件提供的内容。Vuex 源码的入口是 src/index.js。
import { Store, install } from './store' import { mapState, mapMutations, mapGetters, mapActions, createNamespacedHelpers } from './helpers' export default { Store, install, version: '__VERSION__', mapState, mapMutations, mapGetters, mapActions, createNamespacedHelpers }
这里可以一目了然地看到 Vuex 对外暴露的 API。其中, Store 是 Vuex 提供的状态存储类,通常我们使用 Vuex 就是通过创建 Store 的实例(核心部分);install是第三方 Vue 插件的调用方法,即在我们调用Vue.use()时,实际上就是调用了 install 的方法并传入 Vue 的引用;map*的方法是辅助的一些减少我们代码量的工具。
在项目中,引入vuex之后就会调用install 方法,然后再是new一个store实例。所以先介绍install方法,install是在store.js底部,先看代码:
export function install (_Vue) { if (Vue && _Vue === Vue) { if (process.env.NODE_ENV !== 'production') { console.error( '[vuex] already installed. Vue.use(Vuex) should be called only once.' ) } return } Vue = _Vue applyMixin(Vue) }
vue执行.use方法时,会传入对应的vue引用,在store.js头部,定义了一个局部变量Vue ,这里的判断主要是保证 install 方法只执行一次,如果重复执行就报错,如果第一次执行就把_Vue引用赋值给Vue,在store的其他地方也能够使用。最后执行了applyMixin方法。
applyMixin方法是在mixin.js中
export default function (Vue) { const version = Number(Vue.version.split('.')[0]) if (version >= 2) { Vue.mixin({ beforeCreate: vuexInit }) } else { // override init and inject vuex init procedure // for 1.x backwards compatibility. const _init = Vue.prototype._init Vue.prototype._init = function (options = {}) { options.init = options.init ? [vuexInit].concat(options.init) : vuexInit _init.call(this, options) } } /** * Vuex init hook, injected into each instances init hooks list. */ function vuexInit () { const options = this.$options // store injection if (options.store) { this.$store = typeof options.store === 'function' ? options.store() : options.store } else if (options.parent && options.parent.$store) { this.$store = options.parent.$store } } }
他的作用是给 Vue 的实例注入一个 $store 的属性。当Vue版本大于2,调用mixin的方法,传进去vuexInit方法,通过父传子的方式,让所有的组件都注入$store。(版本小于2的现在应该都自动忽略了吧 哈哈哈) 图片来自美团点评技术团队 这样我们在所有的组件中都能通过this.$store来访问到Vuex 的各种数据和状态。
把分析的文章分开,是想以后自己看的时候更清晰一点,如果是一篇文章的话,内容会很多,看起来会很乱。分开的话,一篇对应一部分,这样也可以循序渐进。这一篇相对来说比较简单,所以看起来也比较轻松。
在项目中一直有用到vuex,觉得vuex是真的好用。十分好奇其中的原理是怎么样的,所以就拿源码,对应着网上的文章进行学习。对应的源码地址: vuex源码
源码分析技巧: 网上推荐的方法都是把源码拷到本地,然后就开始看源码,呃。。。。,反正我看了之后是一脸懵逼。可以将源码拷贝到自己的项目中,通过import的方式去引入他(通常我们通过依赖去引入)。这样的好处就是能在他的代码中修改。在控制台输出,打断点...,结合自己项目的使用情况,你就会发现好理解多了。不然光看代码,你很难分析他传经来的参数到底是什么?就会导致后面的分析都会异常的困难。
源码分析
目录结构
src 目录下的文件并不多,module下主要是module的两个构造函数,plugins下面是两个vuex内置插件,还有对应的几个js,整个源码加起来1000行差不多吧(看去年的文章还只有500-600行),虽然量也不是特别大,但是想要完全看明白还是需要花一点时间的。
入口文件
看源码一般是从入口开始,因为我们用的时候也是会通过import的方式去引入。所以入口文件就相当于是桥梁,通过入口文件,去了解插件提供的内容。Vuex 源码的入口是 src/index.js。
这里可以一目了然地看到 Vuex 对外暴露的 API。其中, Store 是 Vuex 提供的状态存储类,通常我们使用 Vuex 就是通过创建 Store 的实例(核心部分);install是第三方 Vue 插件的调用方法,即在我们调用Vue.use()时,实际上就是调用了 install 的方法并传入 Vue 的引用;map*的方法是辅助的一些减少我们代码量的工具。
install
在项目中,引入vuex之后就会调用install 方法,然后再是new一个store实例。所以先介绍install方法,install是在store.js底部,先看代码:
vue执行.use方法时,会传入对应的vue引用,在store.js头部,定义了一个局部变量Vue ,这里的判断主要是保证 install 方法只执行一次,如果重复执行就报错,如果第一次执行就把_Vue引用赋值给Vue,在store的其他地方也能够使用。最后执行了applyMixin方法。
applyMixin方法是在mixin.js中
他的作用是给 Vue 的实例注入一个 $store 的属性。当Vue版本大于2,调用mixin的方法,传进去vuexInit方法,通过父传子的方式,让所有的组件都注入$store。(版本小于2的现在应该都自动忽略了吧 哈哈哈) 图片来自美团点评技术团队 这样我们在所有的组件中都能通过this.$store来访问到Vuex 的各种数据和状态。
把分析的文章分开,是想以后自己看的时候更清晰一点,如果是一篇文章的话,内容会很多,看起来会很乱。分开的话,一篇对应一部分,这样也可以循序渐进。这一篇相对来说比较简单,所以看起来也比较轻松。