[源码学习] Vue
原文链接
Vuex 作为 Vue 官方的状态管理架构,借鉴了 Flux 的设计思想,在大型应用中可以理清应用状态管理的逻辑。为了更清楚的理解它的原理和实现,还是从源码开始读起吧。总共 1000 多行的代码,读起来也相对轻松。
cloc src/
Language files blank comment code
JavaScript 5 53 141 389
SUM: 5 53 141 389
cloc test/
Language files blank comment code
JavaScript 5 62 30 793
SUM: 5 62 30 793
结构梳理
先抛开 middlewares,Vuex 的主要源码一共有三个文件:
file
intro
index.js
Class Store, install,...
override.js
初始化 Vuex
util.js
相关 util(用到了 getWatcher 和 getDeep)
Store
我们使用 Store 创建 Vuex 的实例并传递给 Vue 的根组件。主要包含了 state 和 mutation。Store 创建了一个 data 为 state 的 Vue 实例,使用了 ES6 Class 的 get 和 set 对 state 做了映射,对 state 的重新 set 当然是不允许的,get 则映射到了 this._vm._data。
Store 提供了 dispatch 方法来完成对 state 的修改,和想象中的差不多,在 _mutations 里找到对应 type 的 mutation,参数并入 this.state 传参调用。
override
作为一个 Vue 的插件,Vuex 需要被这样引入:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
Vue 的插件应当有一个公开方法 install。这个方法的第一个参数是 Vue 构造器。 Vuex 的 install 中,在保证单次调用的情况下,调用 override 对 Vue 构造器进入了注入。
override 中对 Vue.prototype._init 注入了 vuexInit,vuexInit 会在每个 instance 的 init hook 中调用。
第一步是绑定 store, Vuex 会寻找 options 中的 store 作为实例的 $store,在不存在时则以递归的方式寻找父组件中的 $store,因此在 Vuex 的项目中,store 只需要在根组件中注入即可。
第二步是处理 vuex, 分别处理其中的 getters 和 actions, 以 example/counter/Counter.vue 为例:
getters
Vuex 用 Object.defineProperty 为每个 getter 在 vm 上绑定了 data,特别的是 getter 作为单向仅 get 数据流,并不能被 set,所以对应的 setter 为报错用的空函数。而 getter 的原理类似于 computed getter,特别的是使用了 store 的 uniqueId 为标识做了缓存,这样同一个 getter 在所有组件中都会使用相同的 watcher。
setter
Action 相对要简单一些,以 $store 作为 action 第一个参数,并将 action 绑定在 instance 上。形成了一个闭环,让 action 访问到 store。
总结
Vuex 源码上粗略的分析基本就到这里了,其实很多地方的代码都很值得细细研究,比如 Store 中的 middlewares 可以完成一些神奇的事情,这里就不一一分析了,画了一张图,按源码的思路大概表达下数据流的意思。O(∩_∩)O
+-----------+ | | | Store +>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>+ | | v |-----------| v | state >>>>- distapatch ->>>>+ v
^ +-----------+ v
^ v
^ +--------------------+ v
^ | | v
^ | Component | v
^ | | v
^ |--------------------| v
^ +>>>>----- getters: {}, |
^ | |
关键字:vuex, vue.js, flux, store
版权声明
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处。如若内容有涉嫌抄袭侵权/违法违规/事实不符,请点击 举报 进行投诉反馈!