全局状态
什么是状态?在代码的世界里,状态就是指数据,简单的理解:你现在的情绪状态是怎样的? “高兴”,“悲伤”,这就是描述你当前情绪状态的数据。
抽象到一个描述用户的Vue组件,当前登录的用户的头像和昵称,就是这个组件的状态(数据);
1.全局状态
从字面意思理解就是,在系统任意地方都可以调用的数据(类似全局变量的概念)。
2.全局变量
全局变量,一般特指系统内任意代码位置都可以调用的变量;
JS有很多实现全局变量,或者类似全局变量的方法:传统的直接在window对象上定义、AMD模块化时在模块内定义然后将模块对象暴露给window,Es6下操作公共的模块;
现在是Es6的时代,所以我们讨论一下Es6的模块(JS至今的模块化规范都有这些特性);
- 模块是一个局部作用域,通过export向外暴露接口;
- 模块在运行时只会初始化一次,在不同地方import引入的都是同一个模块对象
- 模块有着闭包的一些特性。
所以通过模块去实现易于管理的全局变量,是非常容易的。
如何选择
Vue拥有Vuex、pinia两款非常优秀的全局状态管理器,在项目开发中基本是标配了。自从有了它们之后,我们习惯性的将所有全局状态都通过它们来组织使用。
观点
需要响应式的变量用全局状态管理器、不需要响应式的用模块封装;
1.避免过度使用?
先来看看Vuex官网的说明:
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。这个状态自管理应用包含以下几个部分:
- 状态,驱动应用的数据源;
- 视图,以声明方式将状态映射到视图;
- 操作,响应在视图上的用户输入导致的状态变化。
可以看出vuex主要是为了更加友好的管理需要全局响应式的数据,通过它定义的所有数据,都会进行数据代理;
在实际的业务中,有时候我们需要的只是一个全局变量,并不需要它具有响应式的特性。在这种情况下是否还要通过Pinia、Vuex来管理呢?
2.实际案例
假设有一个低代码平台的页面编辑器,需要实现修改后可以撤回,撤回后可以恢复的功能;
页面组成如下:
- 左侧组件选取
- 中间组件根据操作实时更新
- 右侧编辑插入的组件的状态
2.1 总结
- 正在被编辑的页面,它的状态在当前页面是页面上所有组件共享(新增、修改、展示)的;并且是需要响应式(修改后实时更新);
- 用户的每一次修改都需要记录操作前的完整状态(快照);
对于这个修改、撤回的功能,我们可以单独拎出来,作为一个独立模块,而不是通过全局状态管理器,分析:
- 每一次保存的快照是不需要响应式特性的;
- 需要在任意地方都可以调用;
2.2 实现,拆分,模块组成
- 一个数组,用于保存每次产生变化的完整快照;
- 一个监视属性,监视全局状态管理内代表页面状态的那个对象;
- 一个保存快照的方法
- 一个定义保存多少次修改的变量;
- 一个指向指定快照的指针变量;
- 向外暴露一个撤回(将指针指向的快照推回全局状态管理器)方法;
- 向外暴露一个恢复(将指针指向的快照的前一个推回全局状态管理器)方法;
条件:
- 撤回时状态指针向前(小一点的索引)移动;
- 恢复时状态指针向后(大一点的索引)移动;
- 发生正常修改时指针执行最后一个索引;
- 撤回和恢复时,标记不需要记录快照,操作完成后,watch重置这个标记。
- 保存快照之前,数量达到上限时,shift第一个快照后再添加。
2.3 最后
当页面状态比较多的时候,通过上面的方式进行实现,会减少很多用不到的get、set,并且易用性、可维护性也是不差的;相信类似的需求场景还有很多,从这个角度来看,还是具有一定参考价值的。
本文只是个人观点,不具有通用性,仅供参考;