在很多公司中,內(nèi)部都會封裝一些適用于公司內(nèi)部業(yè)務(wù)的方法庫來提高整個團(tuán)隊(duì)的開發(fā)效率,比如:
而在 Vue3 項(xiàng)目中,這種方法庫表現(xiàn)為:hooks庫,市面上有很多優(yōu)秀的庫,比如:vueuse。
最近我在面試中,喜歡問一道有關(guān)于 hooks 的開放問題:二次封裝一個 loaclStorage 的 hooks 時,需要考慮哪些問題呢?
其實(shí)這是一道很簡單的題,只不過想考考面試者在做業(yè)務(wù)的時候,會不會考慮更多的邊界情況~接下來說說我對這個問題的小小的理解(可能也不是很全面)。

比如我現(xiàn)在一個域名下有兩個子項(xiàng)目:
且這兩個項(xiàng)目都需要存儲 userInfo,那要怎么防止這兩組數(shù)據(jù)互相污染呢?所以需要注意命名,在存儲的時候加上對應(yīng)的項(xiàng)目名前綴,或者其他標(biāo)識符,保證這組數(shù)據(jù)是唯一的
const PROJECT_NAME = 'test-project'localStorage.setItem( `${PROJECT_NAME}_userInfo`, JSON.stringify({ name: 'lsx' }))請看一個例子,假如我們存儲一段信息,類型是 string
// 存數(shù)據(jù)const set = () => { const info = get() if (!info) { localStorage.setItem( `${PROJECT_NAME}_info`, 'info_string' ) }}// 取數(shù)據(jù)const get = () => { const info = localStorage.getItem( `${PROJECT_NAME}_info` ) return info}然后項(xiàng)目上線了一段時間,但是這個時候,突然決定要換成 object 類型了,這時候?qū)?yīng)的存取方法也變了
// 存數(shù)據(jù)const set = () => { const info = get() if (!info) { localStorage.setItem( `${PROJECT_NAME}_info`, JSON.stringify({ name: 'lsx' }) ) }}// 取數(shù)據(jù)const get = () => { const info = localStorage.getItem( `${PROJECT_NAME}_info` ) return JSON.parse(info)}但是這樣其實(shí)是有隱患的,因?yàn)轫?xiàng)目已經(jīng)上線了一段時間,有些用戶已經(jīng)存過這個數(shù)據(jù)了,且存的是 string 類型,但是新版本上線之后,取數(shù)據(jù)卻用了 object 的方式去取數(shù)據(jù),這就導(dǎo)致了JSON.parse(字符串)會報錯,影響正常的業(yè)務(wù)邏輯~
所以最好是加一個版本號,或者做一下錯誤兼容,這樣就能避免了~
const PROJECT_NAME = 'test-project'// 每次升級時改變版本號,規(guī)則自己定const VERSION = 1// 存數(shù)據(jù)localStorage.setItem( `${PROJECT_NAME}_userInfo_${VERSION}`, JSON.stringify({ name: 'lsx' }))// 取數(shù)據(jù)localStorage.getItem( `${PROJECT_NAME}_userInfo_${VERSION}`)時效性,那就是給存進(jìn)去的數(shù)據(jù)加一個時效,過了某個時間,這個數(shù)據(jù)就時效了,方法就是每次存數(shù)據(jù)進(jìn)去的時候,加一個時間戳:
// 原來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' }, // 記錄當(dāng)前時間 time: new Date().getTime() }))// 取數(shù)據(jù)時判斷時間戳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}有一些數(shù)據(jù)我們不得不存在 localStorage 中,但是又不想被用戶看到,這時候就需要進(jìn)行加密了(加密規(guī)則自己定):
// 加密函數(shù)const encrypt = (v) => {}// 解密函數(shù)const decrypt = (v) => {}// 存數(shù)據(jù)localStorage.setItem( `${PROJECT_NAME}_userInfo_${VERSION}`, // 加密 encrypt(JSON.stringify({ name: 'lsx' })))// 取數(shù)據(jù) 解密decrypt(localStorage.getItem( `${PROJECT_NAME}_userInfo_${VERSION}`))SSR 就是服務(wù)端渲染,是在服務(wù)端運(yùn)行代碼,拼接成一個頁面,發(fā)送到瀏覽器去展示出來,所以在服務(wù)端是使用不了 localStorage 的,因?yàn)椴皇菫g覽器環(huán)境,所以你像封裝一個比較通用的 localStorage,得兼顧 SSR 的情況:
// 在 SSR 中使用對象替代 localStorageconst SSRStorage = { map: {}, setItem(v) { this.map[key] = v }, getItem(key) { return this.map[key] }}let storage = null// 判斷環(huán)境if (!window) { storage = SSRStorage} else { storage = window.localStorage}
本文鏈接:http://m.www897cc.com/showinfo-26-76567-0.html我面試最喜歡問的開放題:如何嚴(yán)謹(jǐn)二次封裝 localStorage?
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。郵件:2376512515@qq.com
上一篇: 面試官:工作中處理過什么復(fù)雜的前端需求,如何解決的?
下一篇: Redis鎖被別人釋放怎么辦