前端的状态管理(上)
作者:饼干_
前言:
提到状态管理大家可能马上就想到:Vuex
、Redux
、Flux
、Mobx
等等方案。其实不然,不论哪种方案只要内容一多起来似乎都是令人头疼的问题,也许你有适合自己的解决方案又或者简单的注释和区分模块,今天来聊一聊前端的状态管理,如果你有好的建议或问题欢迎在下方留言提出。
1、什么是前端状态管理?
举个例子:图书馆里所有人都可以随意进书库借书还书,如果人数不多,这种方式可以提高效率减少流程,一旦人数多起来就容易混乱,书的走向不明确,甚至丢失。所以需要一个图书管理员来专门记录借书的记录,也就是你要委托图书管理员给你借书及还书。
实际上,大多数状态管理方案都是如上思想,通过管理员(比如 Vuex)去规范书库里书本的借还(项目中需要存储的数据)
2、Vuex
在国内业务使用中 Vuex
的比例应该是最高的,Vuex
也是基于 Flux
思想的产品,Vuex
中的 state
是可以被修改的。原因和 Vue 的运行机制有关系,Vue
基于 ES5
中的 getter/setter
来实现视图和数据的双向绑定,因此 Vuex
中 state
的变更可以通过 setter
通知到视图中对应的指令来实现视图更新。更改 Vuex
的 store
中的状态的唯一方法是提交 mutation
。我们以图书馆来作为例子:
const state = { book: 0 } const mutations = { borrow_book(state) { state.book ++ } } //调用时 store.commit('borrow_book')
那还有action
呢? 在 mutation
中混合异步调用会导致你的程序很难调试。你怎么知道是哪个先执行完呢? aciton
可以包含任意异步操作,用法跟上面基本类似,不再叙述。
其实我只是拿 Vuex 来浅入一下相关用法大家应该是都熟悉了,那 Vuex 解决了什么问题呢?
- 管理多个组件共享状态。
- 全局状态管理。
- 状态变更跟踪。
- 让状态管理形成一种规范,使代码结构更清晰。
实际上大部分程序员都比较懒(狗头保命),只是为了能多个组件共享状态,至于其他的都是事后了。最典型的就是加入购物车的数量,加入一个就通过 Vuex 记录保存最终的总数显示在下栏。
那问题来了,既然你的目的只是共享多个状态,那何不直接用 Bus
总线好了?
3、Bus 总线
Bus
总线实际上他是一个公共的 Vue 实例,专门处理 emit
和 on
事件。
实际上 Bus 总线十分轻便,他并不存在 Dom
结构,他仅仅只是具有实例方法而已。
Vue.prototype.$Bus = new Vue()
然后,你可以通过 emit
来发送事件, on
来接收事件。
// 发送事件 this.$Bus.$emit('borrow_book', 1) // 任意组件中接收 this.$Bus.$on('borrow_book', (book) => { console.log(`借了${book}本书`) })
当然还有 off
(移除)、once
(监听一次)等操作感兴趣可以自行搜索引擎。
怎么样?上面对于满足共享一个状态是不是比 Vuex 要简单多了?实际上确实是简单多了,但这也代表他比较适合中小型项目。多于大型项目来说 Bus
只会让你追述更改源时一脸懵逼甚至你都不知道他在哪里改变了。
他的工作原理就是发布订阅者的思想,虽然非常优雅简单,但实际 Vue
并不提倡这种写法,并在3.0版本中移除了大部分相关Api
(emit、on等),其实不然,发布订阅模式我们可以自己手写一个去实现:
class Bus { constructor() { // 收集订阅信息,调度中心 this.list = {}; } // 订阅 $on(name, fn) { this.list[name] = this.list[name] || []; this.list[name].push(fn); } // 发布 $emit(name, data) { if (this.list[name]) { this.list[name].forEach((fn) => { fn(data); }); } } // 取消订阅 $off(name) { if (this.list[name]) { delete this.list[name]; } } } export default Bus;
简单吧?你只需要跟用 Vue Bus
一样去实例化然后用就可以了。什么?你想共享两三个甚至更少的状态(一个),那封装一个 Bus
是不是有点没必要了? 行吧,那你用 web storage
吧。
4、web storage
其实说到这,storage
只是数据存储方式,跟状态管理其实没有太大关系,只是共享数据。但是既然都提到了那就顺带说一下(狗头)
web storage
有这三种:cookie
、local storage
、session storage
。
无论这三种的哪种都强烈建议不要将敏感信息放入其中,这里应该是加密或一些不那么重要的数据在里面。
先简单复习一下三者:
cookie
不必多说,大家发起请求时经常会携带cokie
请求一些个人数据等,与我们要探讨的内容没有太大关系。loaclStorage
可以存储理论上永久有效的数据,如果你要存储状态一般推荐是放在 sessionStorage
,localStorage
也有以下局限:
- 浏览器的大小不统一,并且在 IE8 以上的 IE 版本才支持
localStorage
这个属性。 - 目前所有的浏览器中都会把
localStorage
的值类型限定为string
类型,这个在对我们日常比较常见的JSON
对象类型需要一些转换。 localStorage
在浏览器的隐私模式下面是不可读取的。localStorage
本质上是对字符串的读取,如果存储内容多的话会消耗内存空间,会导致页面变卡。localStorage
不能被爬虫抓取到。
localStorage
与 sessionStorage
的唯一一点区别就是 localStorage
属于永久性存储,而 sessionStorage
属于当会话结束的时候,sessionStorage
中的键值对会被清空。
localStorage
本身只支持字符串形式存储,所以你存整数类型,拿出来的会是字符串类型。
sessionStorage
与 localStorage
基本差不多,只是回话关闭时,数据就会清空。
总结:
不论哪种方案选择合适自己项目的方案才是最佳实践。没有最好的方案,只有合适自己的方案。
到此这篇关于前端的状态管理的文章就介绍到这了,更多相关前端的状态管理内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!