1. 事件起因 之前做一個駕照考題的項目,有一個這樣的問題,每當我選好了科目和駕照類型後(如圖1),點擊開始考試就會跳到考試頁面(Test.tsx),並且在Test組件中對我架設的中間層發起請求獲取數據(如圖2)。 如果用戶手滑的話不小心點到了左上角的返回,或者狠狠地把屏幕往右滑動一下的話,都會返回 ...
1. 事件起因
之前做一個駕照考題的項目,有一個這樣的問題,每當我選好了科目和駕照類型後(如圖1),點擊開始考試就會跳到考試頁面(Test.tsx),並且在Test組件中對我架設的中間層發起請求獲取數據(如圖2)。
如果用戶手滑的話不小心點到了左上角的返回,或者狠狠地把屏幕往右滑動一下的話,都會返回到首頁,再重新點擊開始考試後進入到Test組件內又會重新發送請求獲取隨機題目,重新渲染題目列表,這樣的話比較消耗性能吧,也是用戶不願意看到的。
圖1
圖2
2. 解決方案
利用「備忘錄」設計模式。
實現思路: 備忘錄其實說白了就是做一次緩存,在發起請求之前先判斷緩存中是否有我要請求的數據,如果有就走緩存,如果沒有就重新請求,請求完了之後再把請求到的數據設置進緩存中。
代碼如下:
src/QuesMemo/index.ts:
// 封裝一個關於考題的備忘錄類, 實例的cache對象中存放所有關於考題的數據
class QuesMemo {
cache: any;
static instance: any;
constructor() {
// cache中存放所有緩存的數據
this.cache = {};
}
static getInstance() {
if(!QuesMemo.instance) {
Object.defineProperty(QuesMemo, 'instance', {
value: new QuesMemo()
});
}
return QuesMemo.instance;
}
// 將數據增添至信息緩存的方法
addMemo(key: string, value: Array<any>) {
this.cache[key] = value;
}
}
export default QuesMemo.getInstance() as object;
下麵來到Test組件內,在請求之前先判斷下緩存中有沒有我要請求的數據,代碼如下:
src/views/Test.tsx:
// 這個是自定義的hook, 裡面就是做了請求數據以及拿到數據後設置當前問題curQuestion的操作, 在Test組件內調用這個hook即可
export function useCurQuestion(): [ IQueryData | null, any ] {
const subject: SUBJECTS = useSelector((state: IState) => state.curSubject);
const model: MODELS = useSelector((state: IState) => state.model);
const [ curQuestion, setCurQuestion ] = useState<IQueryData>(null);
const dispatch: Dispatch = useDispatch();
useEffect(() => {
// 開始判斷cache緩存中是否有我所需要的考題數據, 考題數據的key我定義為 subject-model 的形式
if(quesMemo.cache[`${ subject }-${ model }`]) {
// 如果有考題數據那我就走緩存
let result: IQueryData[] = quesMemo.cache[ `${ subject }-${ model }` ];
dispatch({ type: types.SET_QUERY_LIST, payload: result });
setCurQuestion(result[0]); // 重新進入Test從第一題開始答
}else {
// getQueries是向node中間層發起請求獲取數據哈
getQueries({ subject, model }).then(res => {
console.log('res: ', res);
dispatch({ type: types.SET_QUERY_LIST, payload: res.result });
setCurQuestion(res.result[0]);
// 獲取到了新數據後再把數據丟入緩存
quesMemo.addMemo( `${ subject }-${ model }`, res.result );
});
}
}, [ subject, model, dispatch ]);
return [ curQuestion, setCurQuestion ];
}
以上就是備忘錄設計模式的大致使用了,感覺思路挺簡單的,就是做了一次緩存,請求之前判斷有數據就走緩存,沒數據就重新請求再丟進緩存。
參考書籍 《JavaScript設計模式》 張容銘 著