本文最后更新于 2024-03-22T23:32:46+00:00
状态管理:本质对一个[全局唯一、具有响应式]变量的管理
因为是全局的,那为了流转/使用上的不混乱/冲突等,所以会对其制定流转规则,让变化变得可预测
Vuex
状态流转:actions => mutations => state
state:数据的存储
mutations:唯一的对数据的[同步]操作(增删改查)入口,可以做简单的业务处理
actions:复杂业务逻辑处理(axios 等)的入口,并只能调用 mutations
Vuex 3.x
官方文档:https://v3.vuex.vuejs.org/zh/
使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| 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)
,调用Vuex
的install
方法
install
方法里面写了Vue.mixin({ beforeCreate: vuexInit })
- 所以
Vuex
的注入是通过Vue.mixin()
混入beforeCreate
方法实现
- 并且在
vuexInit
内,定义了this.$store
,实现$store
的挂载
- 通过调用
new Vue
来实现Vuex
的响应式,并且this.$store.state
的获取是通过get
实现的
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
| export class Store { constructor (options = {}) { resetStoreVM(this, state) },
get state () { return this._vm._data.$$state } }
function resetStoreVM(store, state)
store._vm = new Vue({ data: { $$state: state }, computed }
})
|
Vuex 4.x
官方文档:https://vuex.vuejs.org/zh/
使用:
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
| import { createApp } from 'vue' import { createStore } from 'vuex'
const store = createStore({ state () { return { count: 0 } }, mutations: { increment (state) { state.count++ } } })
const app = createApp({ })
app.use(store)
|
原理
- 引入的
createStore
本质是个生成实例的函数
- 通过
app.use(store)
,调用store 实例
的install
方法
install
方法里面写了vue.provide(storeKey, this)
- 所以
Vuex
的注入是通过vue.provide()
实现的
- 并且还定义了
vue.config.globalProperties.$store = this
,实现$store
的挂载
- 通过借用
Vue
的reactive
实现Vuex
的响应式,并且this.$store.state
的获取是通过get
实现的
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
| 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)
store._state = reactive({ data: state })
})
|
Pinia
官方文档:https://pinia.vuejs.org/zh/introduction.html
原理
跟 Vuex 4.x 差不多的
使用了vue
的provide/inject
、vue.config.globalProperties.$store
、reactive
等
其他补充
观察者 & 发布订阅
观察者:不存在一个中心,事件流:A => B
A 干了 xxx,B 观察到了,就直接再行动。
Vue 就是观察者模式,通过拦截数据的读取操作,收集依赖;拦截数据的设置操作,触发依赖
发布订阅:存在一个中心,事件流为:A => 中心 => B
A 干了 xxx,然后通知事件中心,事件中心再去通知对应的订阅者(B),B 再行动
EventBus 就是发布订阅
面试题
手写发布订阅(简单版)
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 32 33 34 35
| class EventBus { constructor() { this.dep = new Map(); }
on(name, fn) { let events = this.dep.get(name);
if (!events) events = new Set();
events.add(fn);
this.dep.set(name, events); }
emit(name, payload) { let events = this.dep.get(name);
if (!events) { throw new Error(`${name} is not registered`); }
events.forEach((cb) => cb(payload)); } }
const eb = new EventBus();
eb.on("log", (value) => { console.log("[ log value ] >", value); });
setTimeout(() => { eb.emit("log", "hello"); }, 5000);
|