vuex commit 模块_vuex核心原理解析

现在前端开发中vue成为主流框架之一,只要不是很小的项目,使用到的诗句都会引用vuex来进行状态管理。最近新开展的项目比较复杂,使用vuex的地方也比较多。在此过程中也遇到了不少问题,进了不少坑,也爬出了好多坑,再这来给大家分享一下

为什么要使用vuex

在当前前端的模块化项目中不可避免的是某些变量需要在全局范围内引用,此时父子组件的传值,子父组件间的传值,兄弟组件间的传值成了我们需要解决的问题。虽然vue中提供了props(父传子)commit(子传父)兄弟间也可以用localstorage和sessionstorage。(在做项目少的时候用这种方式还是方便的)但是这种方式在数据量大的项目开发中带来的问题(难管理,难维护,代码复杂,安全性低)。vuex的诞生也是为了解决这些问题,从而大大提高我们vue项目的开发效率。我通过一段时间,看了一下源码

vuex的整体架构主体

源码解析(工作原理)

根state的存储位置

const store = new Vuex.Store({

state: { count: 0 },

mutations: { increment (state) {

state.count++

} } })

我们设置在跟state中的属性会被vuex存储在根元素中

this._modules = new ModuleCollection(options)//初始化

const state = this._modules.root.state//获取定义的state

vuex初始化时先去获取定义在state属性中的值new ModuleCollection(options)进行模块收集(重新组装我们定义在store中的相关属性):

最终形成一棵module树

export default class ModuleCollection {

constructor (rawRootModule) {

// register root module (Vuex.Store options)

this.register([], rawRootModule, false)

}

get (path) {

return path.reduce((module, key) => {

return module.getChild(key)

}, this.root)

}

getNamespace (path) {

let module = this.root

return path.reduce((namespace, key) => {

module = module.getChild(key)

return namespace + (module.namespaced ? key + '/' : '')

}, '')

}

update (rawRootModule) {

update([], this.root, rawRootModule)

}

register (path, rawModule, runtime = true) {

if (process.env.NODE_ENV !== 'production') {

assertRawModule(path, rawModule)

}

const newModule = new Module(rawModule, runtime)

if (path.length === 0) {

this.root = newModule

} else {

const parent = this.get(path.slice(0, -1))

parent.addChild(path[path.length - 1], newModule)

} // register nested modules

if (rawModule.modules) {

forEachValue(rawModule.modules, (rawChildModule, key) => {

this.register(path.concat(key), rawChildModule, runtime)

})

}

}

unregister (path) {

const parent = this.get(path.slice(0, -1))

const key = path[path.length - 1]

if (!parent.getChild(key).runtime) return

parent.removeChild(key)

}

}

commit(=>mutations)时做了什么

const { dispatch, commit } = this

//初始化先绑定commit

this.commit = function boundCommit(type, payload, options) {

return commit.call(store, type, payload, options)

}

绑定之后注册mutation(commit的属性)

function registerMutation(store, type, handler, local) {

const entry = store._mutations[type] || (store._mutations[type] = [])

entry.push(function wrappedMutationHandler(payload) {

handler.call(store, local.state, payload)

})

}

commit(_type, _payload, _options) {

console.log('my name is zandianhui')

console.log(_type)

console.log(_payload)

console.log(_options)

// check object-style commit

const {

type,

payload,

options

} = unifyObjectStyle(_type, _payload, _options)

const mutation = {

type,

payload

}

//这是一个函数数组

const entry = this._mutations[type]

//判断当前设置的属性的值是否存在

if (!entry) {

if (process.env.NODE_ENV !== 'production') {

console.error(`[vuex] unknown mutation type: ${type}`)

}

return

}

//在执行mutation的时候,会将_committing设置为true,执行完毕后重置,在开启strict模式时,会监听state的变化,当变化时_committing不为true时会给出警告

this._withCommit(() => {

//迭代传入的commit数组

entry.forEach(function commitIterator(handler) {

handler(payload)

})

})

this._subscribers.forEach(sub => sub(mutation, this.state))

//当开发环境是抛出警告(如果commit的属性不存在)

if (

process.env.NODE_ENV !== 'production' &&

options && options.silent

) {

console.warn(

`[vuex] mutation type: ${type}. Silent option has been removed. ` +

'Use the filter functionality in the vue-devtools'

)

}

}

3.dispatch(=>actions)做了啥(初始化同commit)

//dispatch定义位置

this.dispatch = function boundDispatch(type, payload) {

return dispatch.call(store, type, payload)

}

绑定dispatch

function registerAction(store, type, handler, local) {

const entry = store._actions[type] || (store._actions[type] = [])

entry.push(function wrappedActionHandler(payload, cb) {

let res = handler.call(store, {

dispatch: local.dispatch,

commit: local.commit,

getters: local.getters,

state: local.state,

rootGetters: store.getters,

rootState: store.state

}, payload, cb)

//将res函数转为异步 promise

if (!isPromise(res)) {

res = Promise.resolve(res)

}

if (store._devtoolHook) {

return res.catch(err => {

store._devtoolHook.emit('vuex:error', err)

throw err

})

} else {

return res

}

})

}

注册actions dispatch(_type, _payload) {

// check object-style dispatch

const {

type,

payload

} = unifyObjectStyle(_type, _payload)

const action = {

type,

payload

}

const entry = this._actions[type]

if (!entry) {

if (process.env.NODE_ENV !== 'production') {

console.error(`[vuex] unknown action type: ${type}`)

}

return

}

try {

this._actionSubscribers

.filter(sub => sub.before)

.forEach(sub => sub.before(action, this.state))

} catch (e) {

if (process.env.NODE_ENV !== 'production') {

console.warn(`[vuex] error in before action subscribers: `)

console.error(e)

}

}

const result = entry.length > 1 ?

Promise.all(entry.map(handler => handler(payload))) :

entry[0](payload)

return result.then(res => {

try {

this._actionSubscribers

.filter(sub => sub.after)

.forEach(sub => sub.after(action, this.state))

} catch (e) {

if (process.env.NODE_ENV !== 'production') {

console.warn(`[vuex] error in after action subscribers: `)

console.error(e)

}

}

return res

})

}

还请大佬们勿喷,只是个人理解,还请多多指教!!

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值