Vuex
packaging
// package.json
{
name:'vuex'.main:'dist/vuex.common.js'.module:'dist/vuex.esm.js'. }// rollup.main.config.js
export default createEntries([
...
{input:'src/index.js'.file:'dist/vuex.esm.js'.format:'es'.env:'development'},... {input:'src/index.cjs.js'.file:'dist/vuex.common.js'.format:'cjs'.ebv:'development'}])Copy the code
vuex
import { Store, install } from './store'
import { mapState, mapMutations, mapGetters, mapActions, createNamespaceHelpers } from './helpers'
import createLogger from './plugins/logger'
export default{
Store,
install,
version:'__VERSION__',
mapState,
mapMutations,
mapGetters,
mapActions,
createNamespaceHelpers,
createLogger
}
Copy the code
Store
// Determine whether to introduce Vue
let Vue
class Store{
constructor(options = {}){
// Check that the current Vue does not exist and is in the browser,Vue has been mounted, assign a value to Vue variable
if(! Vue &&typeof window! = ='undefined' && window.Vue){
install(window.Vue)
}
const { plugins = [], strict = false } = options
// Assign a private variable
this._commiting = false
this._actions = Object.create(null)
this._actionSubscribers = []
this._mutations = Object.create(null)
this._wrappedGetters = Object.create(null)
this._modules = new ModuleCollection(options)
this._modulesNamespaceMap = Object.create(null)
this._subscribers = []
this._watcherVM = new Vue()
this._makeLocalGettersCache = Object.create(null)
// Point the context of dispatch and commit to the binding
const store = this
const { dispatch, commit } = this
this.dispatch = function boundDispatch(type,payload){
return dispatch.call(store,type,payload)
}
this.commit = function boundCommit(type,payload,options){
return commit.call(store,type,payload,options)
}
this.strict = strict
const state = this._modules.root.state
// Bind global action/getter/mutationss
installModule(this,state,[],this._modules.root)
// Initialize the vm object bound to store
resetStoreVM(this,state)
/ / the plugin application
plugins.forEach(plugin= > plugin(this))
constuseDevtools = options.devtools ! = =undefined ? options.devtools : Vue.config.devtools
if(useDevtools){
devtoolPlugin(this)}}get state() {return this._vm._data.$$state
}
set state(v) {if(__DEV__){
asset(false.`use store.replaceState() to explicit replace store state`)}}commit(_type,_payload,_options){
// Format fetch type,payload,options
const { type, payload, options} = unifyObjectStyle(_type,_payload,_options)
const mutation = { type, payload }
// Get the synchronization event
const entry = this._mutations[type]
if(! entry){if(__DEV__){
console.error(`[vuex] unkonwn mutation type:${type}`)}return
}
// Execute synchronous event logic
this._withCommit(() = > {
entry.forEach(function commitIterator(handler){
handler(payload)
})
})
this._subscribers.slice().forEach(sub= > sub(mutation,this.state))
if(__DEV__ && options && options.slient){
console.warn(`[vuex] mutation type: ${type}. Slient option has been removed. use the filter funtionality in the vue-devtools`)}}dispatch(_type,_payload){
/ / get the type/paylod
const { type, payload }= unifyObjectStyle(_type,_payload)
const action = { type, payload }
const entry = this.actions[type]
if(! entry){if(__DEV__){
console.error(`[vuex] unkonwn action type:${type}`)}return
}
// Perform the plug-in's before operation
try{
this._actionSubscribers.slice().filter(sub= > sub.before).forEach(sub= > sub.before(action,this.state))
}catch(e){
...
}
// Get execution results based on events at Dispatch
const result = entry.length > 1 ? Promise.all(entry.map(handler= > handler(payload))) : entry[0].payload
return new Promise((resolve,reject) = > {
result.then(res= > {
/ / execution plugin. After
try{
this._actionSubscribers.slice().filter(sub= > sub.after).forEach(sub= > sub.afetr(action,this.state))
}catch(e){
...
}
resolve(res)
})
},error= > {
// plugin.error
try{
this._actionSubscribers.slice().filter(sub= > sub.error).forEach(sub= >sub.error(action,this.state,error))
}catch(e){
...
}
reject(error)
})
}
subscribe(fn,options){
// Subscribe to the commit event and return a function to clear the event
return genericSubscribe(fn,this._subscribers,options)
}
subscribeAction(fn,options){
// Subscribe to the action event and return a function to clear the event
const subs = typeof fn === 'function' ? { before: fn} : fn
return genericSubscribe(fn,this._actionSubscribers,options)
}
watch(getter,cb,options){
if(__DEV__){
asset(typeof getter === 'function'.`store.watch only accepts a function`)}// Responsive listening
return this._watcherVM.$watch(() = > getter(this.state,this.getters),cb,options)
}
replaceState(state){
/ / replace state
this._withCommit(() = > {
this._vm._data.$$state = state
})
}
registerModule(path,rawModule,options = {}){
if(typeof path === 'string') path = [path]
if(__DEV__){
assert(Array.isArray(path),`module path must be a string or a Array`)
assert(path.length > 0.`cannot register the root module by using registerModule`)}// Dynamic registration module
this._modules.register(path,rawModule)
// Dynamically register module events/methods /state
installModule(this.this.state,path,this._module.get(path),options.prevState)
resetStoreVM(this.this.state)
}
unregisterModule(path){
if(typeof path === 'string') path = [path]
if(__DEV__){
asset(Array.isArray(path),`module path must be a string or a array`)}// Unmount the module
this._modules.unregister(path)
/ / remove state
this._withCommit(() = > {
const parentState = getNestedState(this.state,path.slice(0, -1))
Vue.delete(parentState,path[path.length - 1])
})
resetStore(this)}hasModule(path){
if(typeof path === 'string') path = [path]
if(__DEV__){
asset(Array.isArray(path),`module path must be a string or a array`)}// Check whether the module is registered
return this._modules.isRegistered(path)
}
hotUpdate(newOptions){
// Hot replace updates module/actions
this._modules.update(newOptions)
// Update the root node status
resetStore(this)}_withCommit(fn){
// Update the status and execute the event
const commiting = this._committing
this._committing = true
fn()
this._committing = committing
}
}
Copy the code