vuex 源代码简析

说明

以下内容均是以 Vuex 2.0.0 版本展开分析。
此篇文章,是自己对 Vuex 实现分析的记录性文章,如有任何错误,欢迎指正交流。

Vuex 示意图
在说之前先来看一张官方文档提供的一张图

首先组件渲染依赖了部分全局的 State 内部预先定义的属性。
组件内部需要更新之前依赖的 State 内部属性,则需要调度(Dispatch)触发 Action 响应状态变化(也可直接提交 mutation)。
响应状态变化函数内部必须提交 mutation 去更改状态(类似发事件)。
State 内部属性的更改,触发依赖其属性的组件重新渲染。

基础示例剖析
了解了大致流程,接下来我们就以基础示例入手,剖析其实现了哪些功能,根据其实现的功能逐步去捋清其代码实现
import Vue from ‘vue’
import Vuex from ‘vuex’

// 注册插件
Vue.use(Vuex)

// 根状态对象。每个Vuex实例只是一个状态树。
const state = { count: 0 }

// mutations 实际上是改变状态的操作。每个 mutation 处理程序都将整个状态树作为第一个参数,然后是附加的有效负载参数。
// mutations 必须是同步的,并且可以通过插件记录下来,以便调试。
const mutations = {
increment (state) {
state.count++
},
decrement (state) {
state.count–
}
}

// actions 是导致副作用并可能涉及异步操作的函数。
const actions = {
increment: ({ commit }) => commit(‘increment’),
decrement: ({ commit }) => commit(‘decrement’),
incrementIfOdd ({ commit, state }) {
if ((state.count + 1) % 2 === 0) {
commit(‘increment’)
}
},
incrementAsync ({ commit }) {
return new Promise((resolve, reject) => {
setTimeout(() => {
commit(‘increment’)
resolve()
}, 1000)
})
}
}

// getters are functions
const getters = {
evenOrOdd: state => state.count % 2 === 0 ? ‘even’ : ‘odd’
}

// 模块
const moduleDemo = {
state: { moduleCount: 1 },
mutations: {
// state: 模块的局部状态对象。
moduleIncrement(state) {
state.moduleCount++
},
},
actions: {
moduleIncrement: ({ commit }) => commit(‘moduleIncrement’),
},
getters: {
moduleCountPlus: ({ moduleCount }) => moduleCount++
}
}

// Vuex实例是通过组合 state、 mutations 、actions 和 getter 创建的。
const store = new Vuex.Store({
state,
getters,
actions,
mutations,
modules: {
moduleDemo
},
})

new Vue({
el: ‘#app’,
store
})

复制代码
根据上述基础使用,我们大概可以梳理出以下几点:
注册插件。
定义 store 所需配置参数。
实例化 Store 类.
实例化 Vue 并传入 store。

在看具体的代码实现之前,我们大致的先了解一下整个 Vuex 入口文件内的大致内容:
import devtoolPlugin from ‘./plugins/devtool’
import applyMixin from ‘./mixin’
import { mapState, mapMutations, mapGetters, mapActions } from ‘./helpers’
import { isObject, isPromise, assert } from ‘./util’

let Vue // 绑定安装

// Store 全局单例模式管理
class Store { … }

// 更新模块
function updateModule(targetModule, newModule) { … }

// 重置 Store
function resetStore(store) { … }

// 重置 Store 上 Vue 实例
function resetStoreVM(store, state) { … }

// 安装模块
function installModule(store, rootState, path, module, hot) { … }

// 注册 mutations 构造器选项
function registerMutation(store, type, handler, path = []) { … }

// 注册 action
function registerAction(store, type, handler, path = []) { … }

// 包装 getters
function wrapGetters(store, moduleGetters, modulePath) { … }

// 启用严格模式
function enableStrictMode(store) {}

// 获取嵌套的状态
function getNestedState(state, path) {}

// 插件注册方法
function install(_Vue) {}

// 自动注册插件
if (typeof window !== ‘undefined’ && window.Vue) {
install(window.Vue)
}

export default {
Store,
install,
mapState,
mapMutations,
mapGetters,
mapActions
}
复制代码在了解了其内部构造,我们就根据上述梳理,逐点分析其实现。
注册插件
我们知道,Vue 的插件都需要给 Vue 提供一个注册钩子函数 installl, 执行 Vue.use(Vuex) 实际内部走的是 install 函数的内部调用。
install

// 插件注册:vue 内部在调用会把 Vue 透传过来
function install(_Vue) {
// 避免重复注册
if (Vue) {
console.error(
‘[vuex] already installed. Vue.use(Vuex) should be called only once.’
)
return
}
// 绑定安装
Vue = _Vue
// 应用全局 Vue.mixins
applyMixin(Vue)
}

// 自动注册机制
if (typeof window !== ‘undefined’ && window.Vue) {
install(window.Vue)
}

复制代码applyMixin
export default function (Vue) {
// 获取 Vue 版本号
const version = Number(Vue.version.split(’.’)[0])

// 版本号为 2.x
if (version >= 2) {
// 若存在 init 钩子则把 VuexInit 混入 初始化阶段
// 其它混入 beforeCreate 阶段
const usesInit = Vue.config._lifecycleHooks.indexOf(‘init’) > -1
Vue.mixin(usesInit ? { i

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值