Vue3状态管理【实践总结】
前端人
共 7261字,需浏览 15分钟
· 2021-03-22
原文地址:juejin.cn/post/6941918738320982023
关注公众号 前端人,回复“加群”
添加无广告优质学习群
状态管理
简述
多个组件,多个模块之间共享状态是最常见的开发述求,场景之多不胜枚举,例如全局用户状态,修改用户信息全局响应变化等等。
常见的解决方案
简单方案基于事件监听机制利用回调传参,多处订阅实现数据的流转。例如官方推荐的mitt事件库。优势简单的数据事件通信是能满足的,劣势随着数据复杂性变动,回调写法的代码阅读性,整体使用体验下降,使用方式也非常简单,具体实现如下:
//定义组合api事件流
const $emitter = mitt()
/**
* @name: useOnChange
* @msg: 监听事件emit
*/
export function useOnChange<T extends Function>(fun: T) {
$emitter.on(EventsEnum.CHANGE, itemMessage => {
fun(itemMessage)
})
}
/**
* @name: useChange
* @msg: 触发事件emit
* @param {*}
*/
export function useChange(itemMessage: number) {
$emitter.emit(EventsEnum.CHANGE, itemMessage)
}
// A组件中触发事件发送数据
export default defineComponent({
name: 'A',
setup() {
//组件A中发送数据
const handlerClick = (item)=>{
//使用组合api发送数据
useChange(1)
}
}
})
// B组件中监听事件获取数据
export default defineComponent({
name: 'B',
setup() {
//回调中获取数据
useOnChange((mes)=>{
console.log(mes)
})
}
})
// C 组件中监听事件获取数据
export default defineComponent({
name: 'C',
setup() {
//回调中获取数据
useOnChange((mes)=>{
console.log(mes)
})
}
})
基于vue3的响应式官方一些简单的实践
const store = {
debug: true,
state: Vue.reactive({
message: 'Hello!'
}),
setMessageAction(newValue) {
if (this.debug) {
console.log('setMessageAction triggered with', newValue)
}
this.state.message = newValue
},
clearMessageAction() {
if (this.debug) {
console.log('clearMessageAction triggered')
}
this.state.message = ''
}
}
const appA = Vue.createApp({
data() {
return {
privateState: {},
sharedState: store.state
}
},
mounted() {
store.setMessageAction('Goodbye!')
}
}).mount('#app-a')
const appB = Vue.createApp({
data() {
return {
privateState: {},
sharedState: store.state
}
}
}).mount('#app-b')
知名状态管理库Redux,Flux,Vuex,这些都是非常优秀的第三方库
为什么明明有vuex你还在折腾啥?
先抛出一个问题大家用了element那么久,请问知道this.$message是怎么实现的吗?如果什么都不管,项目来了上去就是一套全家桶,做一个项目和做十个项目有什么区别?既然新的机会来了为什么自己写一下vue3的组件,vue3的状态管理? 业务与场景在项目初期比较简单,没有记录变更、保存状态快照、历史回滚/时光旅行的诉求,那为什么不自己做一个状态管理呢? 核心实现功能:状态修改单项数据流,状态改变全局数据响应,代码约定,思考一下怎么解决这三个问题?
实现思路
单项数据流,Readonly 状态改变数据响应,组合api和响应式 代码约束 使用ts 进行接口约定
其他大神的一些实现
利用provide 还有一些基于reactive等等一些想法
站在巨人的肩膀上
基于一些大神是vue3封装reduer思路自己也去做了实现
基础实现
import { readonly, ref } from 'vue'
// 全局缓存
const map = new WeakMap()
export function useModel(hook: Function) {
if (!map.get(hook)) {
const ans = hook()
map.set(hook, ans)
}
return map.get(hook)
}
export function useReducer(reducer: Function, initialState = {}) {
const state = ref(initialState)
const dispatch = <T>(action: T) => {
state.value = reducer(action, state.value)
}
return {
state: readonly(state),
dispatch,
}
}
export function useStore(reducer: Function, initialState?: any) {
return useReducer(reducer, initialState)
}
2.实现小型reduer
import { Ref } from 'vue'
import { useModel, useReducer } from './reducer'
// 状态接口
export interface State {
oo: string,
xx: string,
cc: string,
}
// 行为接口
export interface Action {
type: 'changeOO' | 'changeXX' | 'changeCC'//指定action
payload: State
}
// 组合函数使用是 状态接口
export type StateType = Readonly<Ref<State>>
// 使用实例接口
interface Redux {
state: StateType
// 这里不是注释,只是这样的语法mark当不识别,保证优雅性,实际使用时放开注释
//dispatch: <T extends Action>(action: T) => void
}
// 状态变更
function reducer(action: Action, state: State) {
switch (action.type) {
case 'changeOO':
state.oo = action.payload.oo
break
case 'changeXX':
state.xx = action.payload.xx
break
case 'changeCC':
state.cc = action.payload.cc
break
}
return { ...state }
}
// 初始化状态
function useStore() {
const initialState = {
oo: 'oo',
xx: 'xx',
cc: 'cc',
}
return useReducer(reducer, initialState)
}
// 组合api 函数可以被任意组件 在任意地方调用
export function useXXXRedux() {
const redux: Redux = useModel(useStore)
return redux
}
3.调用实现,在任意组件内,或者任何组合api内部,在哪里调用都行
export default defineComponent({
name: 'D',
setup() {
//回调中获取数据
const { state:xxState,dispatch } = useXXXRedux()
//监听state变化
watch(xxState, state => {
})
//触发状态改变
dispatch({type:"changeOO",{payload:{oo:"iii"}}})
})
总结
缺点: 记录变更、保存状态快照、历史回滚/时光旅行的诉求 这些是缺失的 优点:整体代码是简单明了的,无侵入式 熟练使用第三方库是一个开发者的基础素养
安排
回复 资料包
领取我整理的进阶资料包回复 加群
,加入前端进阶群console.log("文章点赞===文章点在看===你我都快乐")
Bug离我更远了,下班离我更近了
评论
知乎热议:博士生最好的状态是什么?
链接:https://www.zhihu.com/question/447412618编辑:深度学习与计算机视觉声明:仅做学术分享,侵删作者:JackieLeehttps://www.zhihu.com/question/447412618/answer/2963078772最好状态比较难说,最开心
机器学习初学者
0
APP 安全测试项总结
一、安装包测试 1.1、关于反编译 目的是为了保护公司的知识产权和安全方面的考虑等,一些程序开发人员会在源码中硬编码一些敏感信息,如密码。而且若程序内部一些设计欠佳的逻辑,也可能隐含漏洞,一旦源码泄漏,安全隐患巨大。 为了避免这些问题,除了代码审核外,通常开发的做法是对代码进行混淆,混淆后源代
测试开发技术
0
大厂都在用的 Git 代码管理规范 !
👉 欢迎加入小哈的星球 ,你将获得: 专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡 / 赠书福利全栈前后端分离博客项目 2.0 版本完结啦, 演示链接:http://116.62.199.48/ ,新项目正在酝酿中
小哈学Java
2
只写后台管理的前端要怎么提升自己
大厂技术 高级前端 Node进阶点击上方 程序员成长指北,关注公众号回复1,加入高级Node交流群本人写了五年的后台管理。每次面试前就会头疼,因为写的页面除了表单就是表格。抱怨过苦恼过也后悔过(虽然我现在已经心安理得的摆烂),但是站在现在的时间点
程序员成长指北
1
微服务与领域驱动设计,架构实践总结
来源:知了一笑👉 欢迎加入小哈的星球 ,你将获得: 专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡 / 赠书福利全栈前后端分离博客项目 2.0 版本完结啦, 演示链接:http://116.62.199.48/ ,新
小哈学Java
0
只要状态对了,事儿也就顺了
卖鸡蛋思维,适合各行各业的套用思维没钱时,牢记卖鸡蛋思维。 请一定耐心看完,成就不一样的你自己。When there‘s no money,Remember the thought of selling eggs.卖鸡蛋思维强调的是商业和经济思维的重要性,从商和创业都应该具备这样的思
小Q聊产品
0
6 个火爆 GitHub 的后台管理模板,快来收藏!
将Python客栈设为“星标⭐”第一时间收到最新资讯今天来给大家介绍6个火爆 G 站的管理后台模板,有了它们,对于前端不是很熟悉的小伙伴来说,再也不用烦恼了,而且有一说一,即使是前端大牛,要想从零开发一套完整的管理模板,也不是一件容易的事情。1. vue-element-admin该项目是基于 Vu
Python客栈
0
【Vuejs】2023- Vue3 项目前端 CI/CD 体验
作者:PAXTONX1. 环境准备➜ app-cicd node --versionv18.0.0➜ app-cicd npm --version9.6.62. 安装2.1 初始化选项项目初始化选择。➜ &
前端自习课
10