3-7 Vue 状态管理-核心源码讲解

128 阅读1分钟

状态管理:本质对一个[全局唯一、具有响应式]变量的管理

因为是全局的,那为了流转/使用上的不混乱/冲突等,所以会对其制定流转规则,让变化变得可预测

Vuex:

状态流转:actions => mutations => state

state:数据的存储

mutations:唯一的对数据的[同步]操作(增删改查)入口,可以做简单的业务处理

actions:复杂业务逻辑处理(axios 等)的入口,并只能调用 mutations

Vuex 3.x

官方文档:v3.vuex.vuejs.org/zh/

使用:

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  }
})

原理:

  • 其中的Store本质是类,所以才new Vuex.Store({ /*...*/ })
  • 通过Vue.use(Vuex),调用Vuexinstall方法
    • install方法里面写了Vue.mixin({ beforeCreate: vuexInit })
      • 所以Vuex的注入是通过Vue.mixin()混入beforeCreate方法实现
    • 并且在vuexInit内,定义了this.$store,实现$store的挂载
  • 通过借用Vue本身实现Vuex的响应式,并且this.$store.state的获取是通过get实现的
export class Store {
  constructor (options = {}) {
    // ......
    resetStoreVM(this, state)
  },
  
	// ......
  
  get state () {
    return this._vm._data.$$state
  }
  // ......
}

function resetStoreVM(store, state)
	// ......

  // ⭐️ 实现 Vuex 的响应式
  store._vm = new Vue({
    data: {
      $$state: state
    },
    computed
  }

  // ......
})

Vuex 4.x

官方文档:vuex.vuejs.org/zh/

使用:

import { createApp } from 'vue'
import { createStore } from 'vuex'
/*
function createStore (options) {
  return new Store(options)
}
*/

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

const app = createApp({ /* 根组件 */ })

// 将 store 实例作为插件安装
app.use(store)

原理:

  • 引入的createStore本质是个生成实例的函数
  • 通过app.use(store),调用store 实例install方法
    • install方法里面写了vue.provide(storeKey, this)
      • 所以Vuex的注入是通过vue.provide() 实现的
      • 并且还定义了vue.config.globalProperties.$store = this,实现$store的挂载
  • 通过借用Vuereactive实现Vuex的响应式,并且this.$store.state的获取是通过get实现的
import { reactive } from 'vue'

export class Store {
  constructor (options = {}) {
    // ......
    resetStoreState(this, state)
  },

  install (vue, injectKey) {
    vue.provide(injectKey || storeKey, this)
    vue.config.globalProperties.$store = this
  }
  
	// ......
  
  get state () {
    return this._state.data
  }
  // ......
}

function resetStoreState(store, state)
	// ......

  // ⭐️ 实现 Vuex 的响应式
  store._state = reactive({
    data: state
  })

  // ......
})

Pinia:

官方文档:pinia.vuejs.org/zh/introduc…

原理:

跟 Vuex 4.x 差不多的

使用了vueprovide/injectvue.config.globalProperties.$storereactive

其他补充

观察者 & 发布订阅

观察者:不存在一个中心,事件流:A => B

A 干了xxx,B 观察到了,就直接再行动。

Vue 就是观察者模式,通过拦截数据的读取操作,收集依赖;拦截数据的设置操作,触发依赖

发布订阅:存在一个中心,事件流为:A => 中心 => B

A 干了xxx,然后通知事件中心,事件中心再去通知对应的订阅者(B),B 再行动

EventBus 就是发布订阅

面试题

手写发布订阅(简单版)