【源码】vuex4 源码浅析

【公司内部分享】探索Vue.js框架内部原理和实现机制,旨在理解其核心概念和技术细节,以便更好地应用和定制Vue.js。

相关文章

环境

  • vuex:v4.1.0

vuex4 源码浅析


一、vue中安装vuex

官网案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { createApp } from 'vue'
import { createStore } from 'vuex'

// 创建一个新的 store 实例
const store = createStore({
state () {
return {
count: 0
}
},
mutations: {
increment (state) {
state.count++
}
}
})

现在,你可以通过 store.state 来获取状态对象,并通过 store.commit 方法触发状态变更

1
2
3
import App from "./App.jsx";
const app = createApp(App)
app.use(store)

将 store 实例作为插件安装,便于组件通过 this.$store 访问,那么app.use()究竟做了什么

官网的描述中,该方法用于安装插件,而插件可以是一个带install方法的对象,或者是一个被用作 install() 方法的函数;那么我们就应当去寻找vuex中的”install”方法

二、vuex中的install方法

回头再看下之前的示例,丢给app.use的store对象是通过createStore方法创建出来的,那就去翻它,vuex源码目录中index文件就导出了这个方法

找到createStore方法的实现,看到了install方法,我们来看看它做了什么

  • 参数app

由vue执行插件的install方法时自动注入

  • 参数injectKey

用于设置设置 Vuex store 的键,用于在一个vue实例中需要配置多个store实例(微前端架构等)

  • app.provide(injectKey || storeKey, this)

这个是给Composition API用的,通过provide方法向所有子孙组件透传了this对象,也就是为什么子孙组件中能通过 useStore 能获取到 store 的关键

  • app.config.globalProperties.$store = this

在vue的全局属性上挂在了$store,也就是子孙组件能通过 this.$store 访问 store的原因

三、useStore 怎么实现的

没想到这个老6,真的就是用inject去接住了前面provide出的store

四、createStore 方法

等等,刚刚我们从app.use一个install方法的方向直接进去了,还没看清楚new Store(options)它究竟做了啥,来,接着奏乐接着舞;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
export class Store {

constructor (options = {}) {

// 省略

// 初始化根模块,递归注册所有子模块,并收集所有模块的 getters 到 this._wrappedGetters 中
installModule(this, state, [], this._modules.root)

// 初始化 store 的状态,负责响应式(也会将 _wrappedGetters 注册为计算属性)
resetStoreState(this, state)

// 省略

}

}

installModule

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
export function installModule (store, rootState, path, module, hot) {

// 省略

// 注册模块的 mutation、action 和 getter
module.forEachMutation((mutation, key) => {
const namespacedType = namespace + key
registerMutation(store, namespacedType, mutation, local)
})

module.forEachAction((action, key) => {
const type = action.root ? key : namespace + key
const handler = action.handler || action
registerAction(store, type, handler, local)
})

module.forEachGetter((getter, key) => {
const namespacedType = namespace + key
registerGetter(store, namespacedType, getter, local)
})

// 遍历当前模块的子模块,对每个子模块递归调用 installModule 函数进行安装。
module.forEachChild((child, key) => {
installModule(store, rootState, path.concat(key), child, hot)
})
}

resetStoreState

  • resetStoreState 函数的作用是重置 Vuex store 的状态,包括重置 getters、创建新的状态、启用严格模式等。
  • 这个函数通常在 Vuex 初始化时被调用,并且在热重载时也会用到。
1
2
3
4
5
6
7
8
9
10
export function resetStoreState (store, state, hot) {

// 省略

store._state = reactive({
data: state
})

// 省略
}

可以发现,resetStoreState内部采用了reactive方法,这也是为什么store里面的数据改变,能通知视图更新。


喜欢这篇文章?打赏一下支持一下作者吧!
【源码】vuex4 源码浅析
https://www.cccccl.com/20230402/源码/vue/vuex4 源码浅析/
作者
Jeffrey
发布于
2023年4月2日
许可协议