在很多公司中,内部都会封装一些适用于公司内部业务的方法库来提高整个团队的开发效率,比如:
而在 Vue3 项目中,这种方法库表现为:hooks库,市面上有很多优秀的库,比如:vueuse。
最近我在面试中,喜欢问一道有关于 hooks 的开放问题:二次封装一个 loaclStorage 的 hooks 时,需要考虑哪些问题呢?
其实这是一道很简单的题,只不过想考考面试者在做业务的时候,会不会考虑更多的边界情况~接下来说说我对这个问题的小小的理解(可能也不是很全面)。
比如我现在一个域名下有两个子项目:
且这两个项目都需要存储 userInfo,那要怎么防止这两组数据互相污染呢?所以需要注意命名,在存储的时候加上对应的项目名前缀,或者其他标识符,保证这组数据是唯一的
const PROJECT_NAME = 'test-project'localStorage.setItem( `${PROJECT_NAME}_userInfo`, JSON.stringify({ name: 'lsx' }))
请看一个例子,假如我们存储一段信息,类型是 string
// 存数据const set = () => { const info = get() if (!info) { localStorage.setItem( `${PROJECT_NAME}_info`, 'info_string' ) }}// 取数据const get = () => { const info = localStorage.getItem( `${PROJECT_NAME}_info` ) return info}
然后项目上线了一段时间,但是这个时候,突然决定要换成 object 类型了,这时候对应的存取方法也变了
// 存数据const set = () => { const info = get() if (!info) { localStorage.setItem( `${PROJECT_NAME}_info`, JSON.stringify({ name: 'lsx' }) ) }}// 取数据const get = () => { const info = localStorage.getItem( `${PROJECT_NAME}_info` ) return JSON.parse(info)}
但是这样其实是有隐患的,因为项目已经上线了一段时间,有些用户已经存过这个数据了,且存的是 string 类型,但是新版本上线之后,取数据却用了 object 的方式去取数据,这就导致了JSON.parse(字符串)会报错,影响正常的业务逻辑~
所以最好是加一个版本号,或者做一下错误兼容,这样就能避免了~
const PROJECT_NAME = 'test-project'// 每次升级时改变版本号,规则自己定const VERSION = 1// 存数据localStorage.setItem( `${PROJECT_NAME}_userInfo_${VERSION}`, JSON.stringify({ name: 'lsx' }))// 取数据localStorage.getItem( `${PROJECT_NAME}_userInfo_${VERSION}`)
时效性,那就是给存进去的数据加一个时效,过了某个时间,这个数据就时效了,方法就是每次存数据进去的时候,加一个时间戳:
// 原来localStorage.setItem( `${PROJECT_NAME}_userInfo`, JSON.stringify({ name: 'lsx' }))const TIME_OUT = 3 * 60 * 60 * 1000// 加时间戳localStorage.setItem( `${PROJECT_NAME}_userInfo`, JSON.stringify({ data: { name: 'lsx' }, // 记录当前时间 time: new Date().getTime() }))// 取数据时判断时间戳const get = () => { let info = localStorage.getItem( `${PROJECT_NAME}_userInfo_${VERSION}` ) info = JSON.parse(info) const now = new Date().getTime() if (now - info.time >= TIME_OUT) { localStorage.removeItem( `${PROJECT_NAME}_userInfo_${VERSION}` ) return null } return info}
有一些数据我们不得不存在 localStorage 中,但是又不想被用户看到,这时候就需要进行加密了(加密规则自己定):
// 加密函数const encrypt = (v) => {}// 解密函数const decrypt = (v) => {}// 存数据localStorage.setItem( `${PROJECT_NAME}_userInfo_${VERSION}`, // 加密 encrypt(JSON.stringify({ name: 'lsx' })))// 取数据 解密decrypt(localStorage.getItem( `${PROJECT_NAME}_userInfo_${VERSION}`))
SSR 就是服务端渲染,是在服务端运行代码,拼接成一个页面,发送到浏览器去展示出来,所以在服务端是使用不了 localStorage 的,因为不是浏览器环境,所以你像封装一个比较通用的 localStorage,得兼顾 SSR 的情况:
// 在 SSR 中使用对象替代 localStorageconst SSRStorage = { map: {}, setItem(v) { this.map[key] = v }, getItem(key) { return this.map[key] }}let storage = null// 判断环境if (!window) { storage = SSRStorage} else { storage = window.localStorage}
本文链接:http://www.28at.com/showinfo-26-76567-0.html我面试最喜欢问的开放题:如何严谨二次封装 localStorage?
声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com
上一篇: 面试官:工作中处理过什么复杂的前端需求,如何解决的?
下一篇: Redis锁被别人释放怎么办