随笔 - 118  文章 - 0 评论 - 341 阅读 - 299万
< 2025年3月 >
23 24 25 26 27 28 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 27 28 29
30 31 1 2 3 4 5

1. 前言

Vuex版本:3.4.0

Vuex仓库:https://github.com/vuejs/vuex

Vux文档:https://vuex.vuejs.org/zh/guide/

文章时间:2020-06-09

 

2. 执行顺序

首先看个简单的代码块:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// store.js
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
 
let baseStore = new Vuex.Store({
    state: {
        count: 0
    },
});
export default baseStore;
 
// app.js
import Vue from 'vue'
import store from './store'
 
new Vue({
    el: '#app',
    store
})

 

2.1 第一步:Vue.use(Vuex)

说明:这一步是Vuex在Vue的beforeCreate事件内增加一个回调函数,其目的是为把初始化后的store对象挂载到this.$store,即Vue.$store。

代码

1
2
3
4
5
6
7
8
9
10
11
Vue.mixin({ beforeCreate: vuexInit });
 
function vuexInit() {
    const options = this.$options;
    // store injection store注入
    if (options.store) {
        this.$store = typeof options.store === 'function' ? options.store() : options.store;
    } else if (options.parent && options.parent.$store) {
        this.$store = options.parent.$store;
    }
}

  

2.2 第二步:new Vuex.Store({})

说明:初始化具体的store对象。

 

2.3 第三步:new Vue({ store })

说明:这里主要是为了执行第一步的代码,因为第一步的Vue.use(Vuex)只是注入一个回调,内部的条件判断options.store 和 options.parent && options.parent.$store都没有生效,只有在这一步时才会生效,其目的就向上面说的把初始化后的store对象挂载到this.$store,这样所有子组件就可以通过this.$store调用store对象。

代码

1
2
3
4
5
6
7
8
9
new Vue({
    el: '#app',
    router,
    components: { App },
    store: {
        baseStore: baseStore
    },
    template: '<App/>'
});

 

3. 探究new Vuex.Store({})

说明:这里将着重介绍new Vuex.Store({})都干了什么。

注意:此处的讲解都是以使用单一状态树为前提条件,没有Module以及Module内的namespaced等知识点,modules这块会单独讲解。

 

3.1 重新绑定dispatch、commit

说明:此处重新绑定dispatch、commit方法,把store自身插入到第一个参数前面。

这也是为什么我们在外部调用this.$store.dispatch('actionName')时,所创建的action第一个参数为store本身。

代码

1
2
3
4
5
6
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)
}

 

3.2 转换为Module对象

说明:在这里Vuex将传入的Vuex代码解析为Model对象(后面将以options表示传入的代码块):

1
2
3
4
5
6
7
8
new Vuex.Store({
    state: {
        count: 0
    },
    getters,
    actions,
    mutations
});

在Vuex源码中,会将options转换为Module集合:

代码

1
// src/store.js<br><br>this._modules = new ModuleCollection(options)

其this._modules,即Model对象初始化后的字段含义为:

1
2
3
4
5
6
7
root: { // Module对象
    state:{
    count: 0
  } // 传入Vuex({options})内的state
    _children: {} // 内部嵌套Module
    _rawModule: options // 传入的options对象
}

 

3.3 installModule

说明:在这里将对Module进行封装处理。

处理步骤

1) 若module.namespaced = true : 此Module将被加入store._modulesNamespaceMap内,其key为Module嵌套的路径。

2) 非root Module时:子Module.state注入到父节点的state对象里。

3)  对store进行局部化,这里主要对module.namespaced= true 的module进行另外处理,其内部的成员都需要进行namespace路径处理处理。

官方说明:默认情况下,模块内部的 action、mutation 和 getter 是注册在全局命名空间的——这样使得多个模块能够对同一 mutation 或 action 作出响应。 如果希望你的模块具有更高的封装度和复用性,你可以通过添加 namespaced: true 的方式使其成为带命名空间的模块。当模块被注册后,它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名。

4) 对module的mutation进行封装:

  ①添加到store._mutations数组内,_mutations的key默认为mutation的名称,如果module.namespaced = true,那么key就为namespace+mutation的名称。可多个module注册同名。

  ②将module.mutation第二个参数修改为局部化的state。

5) 对module的action进行封装:

  ①添加到store._actions数组内,_actions的key默认为action的名称,如果module.namespaced = true,那么key就为namespace+action的名称。可多个module注册同名。

  ②将module.action第二个参数修改为局部化和root的state。

6) 对module的getter进行封装:

  ①添加到store._wrappedGetters数组内,_wrappedGetters的key默认为action的名称,如果module.namespaced = true,那么key就为namespace+action的名称。只能单一注册。

  ②module.mutation第一个参数修改为局部化和root的state。

7) 若当前module含有子module时,遍历当前model的_children属性,迭代执行installModule。

 

3.4 resetStoreVM

说明:初始化storevm,并负责将getter注册为计算属性,并保存缓存特性。

处理步骤:

1) 遍历wrappedGetters,封装到store.getters里。

2) 初始化store._vm,传入data和computed。

说明:这里主要把state与getter(computed)进行绑定,state有更改时,getter(computed)进行自动更新,采用的方式就是本地创建一个Vue对象。

 

3.5 注册插件

 

4. commit()执行了什么

当在action内调用了commit方法时,其内部步骤如下:

1) 从store._mutations[]数组内读取对应的mutation名称的数组。

2) 从获取到的_mutations[]数组遍历执行对应的mutation处理程序。

3) 触发store._subscribers对应的回调。

 

5. dispatch()执行了什么

在通过this.$store.dispatch()调用对应的action时,其内部步骤如下:

1) 与commit()调用的方法类似,从store._actions[]数组内获取对应的acticon数组。

2) 执行active对应的处理程序并以Promise返回。

 

posted on   FangMu  阅读(4756)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
点击右上角即可分享
微信分享提示