如何保存頁面的當前的狀態?
- 既然是要保持頁面的狀態(其實也就是組件的狀態),那么會出現以下兩種情況:
- 組件會被卸載:
- (1)將狀態存儲在LocalStorage / SessionStorage
- 優點:
- 缺點:
- (2)路由傳值
- 優點:
- 缺點:
- 組件不會被卸載:
- (1)單頁面渲染
- 優點:
- 缺點:
- 用keep-alive緩存頁面
既然是要保持頁面的狀態(其實也就是組件的狀態),那么會出現以下兩種情況:
組件會被卸載:
(1)將狀態存儲在LocalStorage / SessionStorage
只需要在組件即將被銷毀的生命周期 componentWillUnmount (react)中在 LocalStorage / SessionStorage 中把當前組件的 state 通過 JSON.stringify() 儲存下來就可以了。在這里面需要注意的是組件更新狀態的時機。比如從 B 組件跳轉到 A 組件的時候,A 組件需要更新自身的狀態。但是如果從別的組件跳轉到 B 組件的時候,實際上是希望 B 組件重新渲染的,也就是不要從 Storage 中讀取信息。所以需要在 Storage 中的狀態加入一個 flag 屬性,用來控制 A 組件是否讀取 Storage 中的狀態。
優點:
兼容性好,不需要額外庫或工具。
簡單快捷,基本可以滿足大部分需求。
缺點:
狀態通過 JSON 方法儲存(相當于深拷貝),如果狀態中有特殊情況(比如 Date 對象、Regexp 對象等)的時候會得到字符串而不是原來的值。(具體參考用 JSON 深拷貝的缺點)
如果 B 組件后退或者下一頁跳轉并不是前組件,那么 flag 判斷會失效,導致從其他頁面進入 A 組件頁面時 A 組件會重新讀取 Storage,會造成很奇怪的現象
(2)路由傳值
通過 vue-router 的 Link 組件的 prop —— to 可以實現路由間傳遞參數的效果。
在這里需要用到 state 參數,在 B 組件中通過 history.location.state 就可以拿到 state 值,保存它。返回 A 組件時再次攜帶 state 達到路由狀態保持的效果。
優點:
簡單快捷,不會污染 LocalStorage / SessionStorage。
可以傳遞 Date、RegExp 等特殊對象(不用擔心 JSON.stringify / parse 的不足)
缺點:
如果 A 組件可以跳轉至多個組件,那么在每一個跳轉組件內都要寫相同的邏輯。
組件不會被卸載:
(1)單頁面渲染
要切換的組件作為子組件全屏渲染,父組件中正常儲存頁面狀態。
優點:
代碼量少
不需要考慮狀態傳遞過程中的錯誤
缺點:
增加 A 組件維護成本
需要傳入額外的 prop 到 B 組件
無法利用路由定位頁面
用keep-alive緩存頁面
除此之外,在Vue中,還可以是用keep-alive來緩存頁面,當組件在keep-alive內被切換時組件的activated、deactivated這兩個生命周期鉤子函數會被執行
被包裹在keep-alive中的組件的狀態將會被保留:
<keep-alive><router-view v-if="$route.meta.keepAlive"></router-view>
</kepp-alive>
router.js
{path: '/',name: 'xxx',component: ()=>import('../src/views/xxx.vue'),meta:{keepAlive: true // 需要被緩存}
},