基于注入的一种状态管理的思路

简介: 基于注入的一种状态管理的思路

开始尝试做自己的状态管理。


上文说了,我们可以定义一个 reactive 结构的userOnline ,然后注入到根组件里面,那么相关的处理函数要怎么办呢?


我们可以写一个单独的js文件,然后用import的方式引入进来,然后我们就可以做统一的处理了。


js文件如下:


import { provide, inject, reactive, readonly } from 'vue'
import sysUserInfo from './symbol'
const userState = () => {
  // 定义标识
  // const sysUserInfo = Symbol('userOnlineInfo')
  // 存放当前登录的用户信息
  const userInfo = reactive({
    isLogon: false,
    isOnline: false,
    userId: 1,
    userCode: 'jyk',
    userNike: '海洋',
    departmentId: 123,
    departmentName: '',
    role: [1],
    power: [1, 2, 3]
  })
  // 在当前组件里面注入
  const register = () => {
    provide(sysUserInfo, userInfo)
  }
  // 获取共享的用户状态
  const _user = inject(sysUserInfo)
  // 设置登录用户的信息
  const setUser = (user) => {
    Object.assign(_user, user)
  }
  // 返回注入的状态,只读形式
  const getUser = () => {
    return readonly(_user)
  }
  // 返回当前用户是否登录
  const isLogon = () => {
    return _user.isLogon
  }
  return {
    // 返回组件内状态
    userInfo: readonly(userInfo),
    // 在组件里注入状态,可以实现子组件共享
    register,
    // 修改状态的函数
    setUser,
    // 获取共享的状态
    getUser,
    // 返回是否登录的状态
    isLogon
  }
}
export default userState
复制代码


定义一个 reactive的 userInfo,实现响应式



在函数内部定义 userInfo,然后在return的时候加上readonly作为限制,这样可以就以避免误操作而导致直接改变状态。


这里获取状态有两种方式,一个是在注入的组件的获取方式,一个是在子组件获取的方式。

因为在注入的组件似乎不能用 inject 来获取,所以只好直接返回 userInfo。于是就出现了两种获取状态的方式。


使用的时候不要弄混。


如果可以保证在注入的组件里面不会用到状态的话,可以把直接返回状态的给去掉,这样就不会混淆了。


使用 register 方式注入



引入js文件并不会自动注入,而是需要显性使用 register  来注入。


这样可以明确注入的组件,另外也可以避免每个组件都注入一个。


如果不使用 register 的话,那么就是完全的本组件使用。


getUser



获取状态的时候,一个要注意使用 inject ,这样获取的才是共享的状态,否则就是本组件内部的单独的状态了。


另外要加上 readonly,确保是只读状态。 当然如果你就是喜欢直接改变状态,那么也可以不加readonly。


setUser



这里有两个注意点。 一个是要加到 inject 获取出来的状态上,否则就是只能改变本组件的状态,除非你在跟组件改状态。


另一个就是应为用的是 reactive,所以不能直接赋值的方式来修改,但是一个一个属性修改也太麻烦了,所以这里采用 Object.assign(_user, user) 的方式来修改属性。


这是ES6提供的一种方法,用后面的对象的属性,覆盖前面的对象的属性。


注意:这种方法有可能导致增加属性。


使用 Symbol 避免重名



export const sysUserInfo = Symbol('userOnlineInfo')
复制代码


一开始我没把这个写在 单独的js文件里面,但是发现子组件里面读取不出来状态,所以只好把  Symbol 放在单独的js文件里面了。


一开始用他是想彻底堵住直接修改状态的漏洞,但是发现好像还是不行。


所以现在就变成了避免重名、避免“魔术”的功能。


似乎应该用纯大写字母来命名,但是,英语重来没及格过,看纯大写的实在头疼。如果你们喜欢的话,你们可以用。


反正组件里面也看不到。


根组件注入



import userState from './store-nf'
setup () {
    const { userInfo, register } = userState()
    // 在这个组件里面注入,子组件里面可以共享状态
    register()
    setTimeout(() => {
      userInfo.userCode = '222222' // 只读状态,不会修改,F12会给出警告。
      console.log('userInfo--定时修改', userInfo)
    }, 500)
}
复制代码


子组件调用


import userState from '../store-nf'
 setup () {
    const { userInfo, getUser } = userState()
    // 测试控件内部修改
    const test = getUser()
    test.userNike = '4345555' // 只读,不让改。
    // 使用指定的方法修改状态
    setUser({ userCode: '22222' })
}
复制代码


基本思路就是这样。 现在这个样子还是比较简陋,大概会有一些不足的地方。


模块化



这样使用本身就变成了一个个独立的模块,或者是一个个独立的管理类。


如果都是在根组件里面注入的话,那么就都是兄弟模块,没有上下级关系。


如果在不同的组件里面注入,那么依赖组件的层级关系来确定上下级的关系。


这样就避免的Vuex里面的模块的命名空间的问题。


不过这样也太分散了,是不是有点不便于统一管理呢?



相关文章
|
2月前
|
Java Spring
Spring初始化加速的思路和方案问题之在BeanFactory#doGetBean方法中,栈状态的变化影响bean的初始化的问题如何解决
Spring初始化加速的思路和方案问题之在BeanFactory#doGetBean方法中,栈状态的变化影响bean的初始化的问题如何解决
|
3月前
new 一个对象的过程中发生了什么
new 一个对象的过程中发生了什么
|
2月前
|
JSON 前端开发 Java
前后端数据交互-----表单数据获取不到,出错的原因,在编写接口时,没有考虑数据如何返回,解决问题的思路,找到自己出错的地方,围绕着出错的地方进行考虑(很重要),找对解决问题的视频,理清返回数据的思路
前后端数据交互-----表单数据获取不到,出错的原因,在编写接口时,没有考虑数据如何返回,解决问题的思路,找到自己出错的地方,围绕着出错的地方进行考虑(很重要),找对解决问题的视频,理清返回数据的思路
|
4月前
|
SQL XML Java
MyBatis初探:揭示初始化阶段的核心流程与内部机制
MyBatis初探:揭示初始化阶段的核心流程与内部机制
49 2
MyBatis初探:揭示初始化阶段的核心流程与内部机制
|
4月前
|
Prometheus Kubernetes Java
ChaosBlade注入问题之查看实现模块位置如何解决
ChaosBlade 是一个开源的混沌工程实验工具,旨在通过模拟各种常见的硬件、软件、网络、应用等故障,帮助开发者在测试环境中验证系统的容错和自动恢复能力。以下是关于ChaosBlade的一些常见问题合集:
|
4月前
|
Java Spring
玩转对象掌控权:深入Spring,精准控制对象创建次数
玩转对象掌控权:深入Spring,精准控制对象创建次数
31 0
|
4月前
|
设计模式 Java 数据库连接
面试题:一个组件向自己内部注入组件有哪些方法?
面试题:一个组件向自己内部注入组件有哪些方法?
40 0
|
11月前
|
Java 数据库 开发者
自动配置要点解读
自动配置要点解读
|
9月前
|
内存技术
SpringMVC运行流程分析之前置流程
SpringMVC运行流程分析之前置流程
40 0
|
存储 SQL Java
Spring事务管理的底层逻辑—源码解析
首先进入CglibAopProxy.class的intercept方法打上一个Debug断点调试,或者在JdkDynamicAopProxy.class的invoke方法(如果目标方法是继承接口方式实现),根据不同实现方法类型选择不同的动态代理类
Spring事务管理的底层逻辑—源码解析