前言
这篇文章是【前端词典】系列文章的第 13 篇文章,接下的 9 篇我会围绕着 Vue 展开,希望这 9 篇文章可以使大家加深对 Vue 的了解。当然这些文章的前提是默认你对 Vue 有一定的基础。如果一点基础都没有,建议先看官方文档。
第一篇文章我会结合 Vue 和 Vuex 的部分源码,来说明 Vuex 注入 Vue 生命周期的过程。
说到源码,其实没有想象的那么难。也和我们平时写业务代码差不多,都是方法的调用。但是源码的调用树会复杂很多。
为何使用 Vuex
使用 Vue 我们就不可避免的会遇到组件间共享的数据或状态。应用的业务代码逐渐复杂,props、事件、事件总线等通信的方式的弊端就会愈发明显。这个时候我们就需要 Vuex 。Vuex 是一个专门为 Vue 设计的状态管理工具。
状态管理是 Vue 组件解耦的重要手段。
它借鉴了 Flux、redux 的基本思想,将状态抽离到全局,形成一个 Store。
Vuex 不限制你的代码结构,但需要遵守一些规则:
- 应用层级的状态应该集中到单个 store 对象中
- 提交 mutation 是更改状态的唯一方法,并且这个过程是同步的
- 异步逻辑都应该封装到 action 里面
Vuex 注入 Vue 生命周期的过程
我们在安装插件的时候,总会像下面一样用 Vue.use()
来载入插件,可是 Vue.use()
做了什么呢?
1 | javascript复制代码import Vue from 'vue'; |
Vue.use() 做了什么
安装 Vue.js 插件。如果插件是一个对象,必须提供 install 方法。如果插件是一个函数,它会被作为 install 方法。install 方法调用时,会将 Vue 作为参数传入。
以上是 官方文档 的解释。
接下来我们从源码部分来看看 Vue.use()
都做了什么。
Vue 源码在 initGlobalAPI
入口方法中调用了 initUse (Vue)
方法,这个方法定义了 Vue.use()
需要做的内容。
1 | javascript复制代码function initGlobalAPI (Vue) { |
这段代码主要做了两件事情:
- 一件是防止重复安装相同的 plugin
- 另一件是初始化 plugin
插件的 install 方法
看完以上源码,我们知道插件(Vuex)需要提供一个 install
方法。那么我们看看 Vuex 源码中是否有这个方法。结果当然是有的:
1 | ini复制代码/* 暴露给外部的 install 方法 */ |
这段代码主要做了两件事情:
- 一件是防止 Vuex 被重复安装
- 另一件是执行
applyMixin
,目的是执行vuexInit
方法初始化 Vuex
接下来 我们看看 applyMixin(Vue)
源码:
1 | php复制代码/* 将 vuexInit 混淆进 Vue 的 beforeCreate */ |
从上面的源码,可以看出 Vue.mixin
方法将 vuexInit
方法混淆进 beforeCreate
钩子中,也是因为这个操作,所以每一个 vm 实例都会调用 vuexInit
方法。那么 vuexInit
又做了什么呢?
vuexInit()
我们在使用 Vuex 的时候,需要将 store 传入到 Vue 实例中去。
1 | arduino复制代码new Vue({ |
但是我们却在每一个 vm 中都可以访问该 store,这个就需要靠 vuexInit
了。
1 | csharp复制代码 function vuexInit () { |
根节点存在 stroe 时,则直接将
options.store
赋值给this.$store
。否则则说明不是根节点,从父节点的$store
中获取。
通过这步的操作,我们就以在任意一个 vm 中通过 this.$store 来访问 Store 的实例。接下来我们反过来说说 Vue.mixin()。
Vue.mixin()
全局注册一个混入,影响注册之后所有创建的每个 Vue 实例。插件作者可以使用混入,向组件注入自定义的行为。不推荐在应用代码中使用。
在 vue 的 initGlobalAPI
入口方法中调用了 initMixin$1(Vue)
方法:
1 | kotlin复制代码function initMixin$1 (Vue) { |
Vuex 注入 Vue 生命周期的过程大概就是这样,如果你感兴趣的话,你可以直接看看 Vuex 的源码,接下来我们说说 Store。
Store
上面我们讲到了 vuexInit
会从 options 中获取 Store。所以接下来会讲到 Store 是怎么来的呢?
我们使用 Vuex 的时候都会定义一个和下面类似的 Store 实例。
1 | javascript复制代码import Vue from 'vue' |
不要在发布环境下启用严格模式。严格模式会深度监测状态树来检测不合规的状态变更 —— 请确保在发布环境下关闭严格模式,以避免性能损失。
state 的响应式
你是否关心 state 是如何能够响应式呢?这个主要是通过 Store 的构造函数中调用的 resetStoreVM(this, state)
方法来实现的。
这个方法主要是重置一个私有的 _vm(一个 Vue 的实例) 对象。这个 _vm 对象会保留我们的 state 树,以及用计算属性的方式存储了 store 的 getters。现在具体看看它的实现过程。
1 | scss复制代码/* 使用 Vue 内部的响应式注册 state */ |
state 的响应式大概就是这样实现的,也就是初始化 resetStoreVM 方法的过程。
看看 Store 的 commit 方法
我们知道 commit 方法是用来触发 mutation 的。
1 | typescript复制代码commit (_type, _payload, _options) { |
该方法先进行参数风格校验,然后利用 _withCommit
方法执行本次批量触发 mutation
处理函数。执行完成后,通知所有 _subscribers
(订阅函数)本次操作的 mutation
对象以及当前的 state
状态。
热门文章传送门
- 【前端词典】滚动穿透问题的解决方案
- 【前端词典】5 种滚动吸顶实现方式的比较(性能升级版)
- 【前端词典】提高幸福感的 9 个 CSS 技巧
- 【前端词典】分享 8 个有趣且实用的 API
- 【前端词典】从输入 URL 到展现涉及哪些缓存环节(非常详细)
本文转载自: 掘金