You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
// src/store.jsexportfunctioninstall(_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=_VueapplyMixin(Vue)}
// src/store.jsclassStore{constructor(options={}){// Auto install if it is not done yet and `window` has `Vue`.// To allow users to avoid auto-installation in some cases,// this code should be placed here. See #731if(!Vue&&typeofwindow!=='undefined'&&window.Vue){install(window.Vue)}if(process.env.NODE_ENV!=='production'){assert(Vue,`must call Vue.use(Vuex) before creating a store instance.`)assert(typeofPromise!=='undefined',`vuex requires a Promise polyfill in this browser.`)assert(thisinstanceofStore,`store must be called with the new operator.`)}const{
plugins =[],
strict =false}=options// store internal statethis._committing=falsethis._actions=Object.create(null)this._actionSubscribers=[]this._mutations=Object.create(null)this._wrappedGetters=Object.create(null)this._modules=newModuleCollection(options)this._modulesNamespaceMap=Object.create(null)this._subscribers=[]this._watcherVM=newVue()// bind commit and dispatch to selfconststore=thisconst{ dispatch, commit }=thisthis.dispatch=functionboundDispatch(type,payload){returndispatch.call(store,type,payload)}this.commit=functionboundCommit(type,payload,options){returncommit.call(store,type,payload,options)}// strict modethis.strict=strictconststate=this._modules.root.state// init root module.// this also recursively registers all sub-modules// and collects all module getters inside this._wrappedGettersinstallModule(this,state,[],this._modules.root)// initialize the store vm, which is responsible for the reactivity// (also registers _wrappedGetters as computed properties)resetStoreVM(this,state)// apply pluginsplugins.forEach(plugin=>plugin(this))constuseDevtools=options.devtools!==undefined ? options.devtools : Vue.config.devtoolsif(useDevtools){devtoolPlugin(this)}}
// store internal statethis._committing=falsethis._actions=Object.create(null)this._actionSubscribers=[]this._mutations=Object.create(null)this._wrappedGetters=Object.create(null)this._modules=newModuleCollection(options)this._modulesNamespaceMap=Object.create(null)this._subscribers=[]this._watcherVM=newVue()
把 Store 上的 commit 和 dispatch 方法绑定到当前 store 实例上,主要通过 call 方法改变 this 指向来实现
// bind commit and dispatch to selfconststore=thisconst{ dispatch, commit }=thisthis.dispatch=functionboundDispatch(type,payload){returndispatch.call(store,type,payload)}this.commit=functionboundCommit(type,payload,options){returncommit.call(store,type,payload,options)}
Vue 初始化核心
installModule
这段代码是初始化的核心,通过 options 上的 modules, 分别注册和安装。
// init root module.// this also recursively registers all sub-modules// and collects all module getters inside this._wrappedGettersinstallModule(this,state,[],this._modules.root)// initialize the store vm, which is responsible for the reactivity// (also registers _wrappedGetters as computed properties)resetStoreVM(this,state)// apply pluginsplugins.forEach(plugin=>plugin(this))
installModule 接收5个参数,各个参数分别表示:
store 表示当前 Store 实例
rootState 表示根 state
path 表示当前嵌套模块的路径数组
module 表示当前安装的模块
hot 表示热更新的时候为 true
functioninstallModule(store,rootState,path,module,hot){constisRoot=!path.lengthconstnamespace=store._modules.getNamespace(path)// register in namespace mapif(module.namespaced){store._modulesNamespaceMap[namespace]=module}// set stateif(!isRoot&&!hot){constparentState=getNestedState(rootState,path.slice(0,-1))constmoduleName=path[path.length-1]store._withCommit(()=>{Vue.set(parentState,moduleName,module.state)})}constlocal=module.context=makeLocalContext(store,namespace,path)module.forEachMutation((mutation,key)=>{constnamespacedType=namespace+keyregisterMutation(store,namespacedType,mutation,local)})module.forEachAction((action,key)=>{consttype=action.root ? key : namespace+keyconsthandler=action.handler||actionregisterAction(store,type,handler,local)})module.forEachGetter((getter,key)=>{constnamespacedType=namespace+keyregisterGetter(store,namespacedType,getter,local)})module.forEachChild((child,key)=>{installModule(store,rootState,path.concat(key),child,hot)})}
entry
Vuex
的入口在src的index
文件下当我们使用
Vuex
插件的时候,我们会在实例创建前这样调用Vue.use(vuex)
,其内部实际上是调用了install
方法install
方法是这样的,传入了Vue的引用,然后调用了applyMixin方法mixin.js里定义了applyMixin方法,主要作用是在Vue的生命周期中的初始化(1.0是init,2.0是beforeCreated)钩子前插入Vuex的初始化代码。
这个方法给Vue的实例注入了$store属性,方便我们在Vue组件里通过this.$store访问到Vuex的各种数据和状态,当然也包括各个子模块下的数据。
初识Store构造函数
当我们使用Vuex的时候,如
new Vuex.Store()
的时候,会传入一个对象,对象上有state、 getters、actions等等,实例化的时候,内部到底做了什么事情,这是我们比较关心的,我们来看下内部Store类的构成。import 'babel-polyfill
assert实现也很简单
使用ES6的解构拿到
plugins
, 默认不开启严格模式,你也可以像这样,在开发模式下开启严格模式,任何手动改变state
都会发出警告this._committing
标志提交状态,确保 state 的改变只在 mutations 的回调函数当中this._actions
存储用户初始化实例传入的所有 actionsthis._mutations
存储用户初始化实例传入的所有 mutationsthis._wrappedGetters
存储用户初始化实例传入的所有 gettersthis._modules
用来存储所有运行时的modulesthis._subscribers_
用来存储所有对mutation变化的订阅者this._watcherVM
是一个Vue对象实例,利用Vue实例方法$watch来检测变化把 Store 上的 commit 和 dispatch 方法绑定到当前 store 实例上,主要通过 call 方法改变 this 指向来实现
Vue 初始化核心
这段代码是初始化的核心,通过 options 上的 modules, 分别注册和安装。
installModule 接收5个参数,各个参数分别表示:
我们在调用这个函数的时候传入了
installModule(this, state, [], options)
,对应的 options 传给了 module, options 可以拿到 state、actions 已经嵌套的 modulesregisterAction 是对 store 中 action 的初始化,参数与 registerMutation 一致,不同的是 mutation 是同步修改当前模块的 state, action 是异步改变 state, 仍然需要提交 mutation 去改变 state, 只是延迟提交而已
isPromise 检查是否为 Promise 对象
一个例子理解 action
定义一个 action, 提交 commit, 在成功或失败,提交不同的 mutation
action 的调用是通过 dispatch 来实现的
type 表示 action 的类型, payload 表示额外的参数
mapActions
Reference
The text was updated successfully, but these errors were encountered: