[Day25]:一個大Store - Store改寫
一個大Store
想要我的狀態嗎? 想要的話可以全部給你,去找吧!我把所有狀態都放在Store裡。───────────────────────── By 哥爾‧D‧羅傑
目標: 改寫Store
過程:
原先的store
javascript// index.js import { createStore } from "vuex"; import user from "./user"; // 登入、使用者相關 import route from "./route"; // 路由相關 export default createStore({ state: {}, getter: {}, actions: {}, // 變動state 用(可非同步) mutations: {} // 變動 state 用(只能同步) modules: { user, route }, });
1
2
3
4
5
6
7
8
9
10
11
12看的出來有兩個
modules
, 我們一個一個來處理:1. user.js
這段式原先的JS 我們複製一個,丟進
'src/store/'
裡, 並把檔名改成user.ts
會發現很多地方開始提醒你有問題:javascript// user.ts import { Base64 } from "js-base64"; export const state = { isLogin: false, // 是否有登入 jwtToken: '', userData: { // 登入資訊 user: '', name: '', /** 使用者權限劃分 permission level * 0 最高管理者 全開 * 1 網站管理者 * 2 一般使用者 * 3 訪客 */ auth: '3', }, }; export const actions = {};// 非同步 export const mutations = { // 同步 signIn(state) { state.isLogin = true; }, signOut(state) { state.isLogin = false; }, /** 將登入後的 Token 轉 成userData * @param {*} state * @param {JWT} JWT */ setUser(state, JWT) { state.jwtToken = JWT; // JWT = header.payload.Signature const Token = JWT.split("."); // 解析使用者資料 const data = JSON.parse(Base64.decode(Token[1])); // 記錄登入者資訊 state.userData.user = data.user; state.userData.name = data.name; state.userData.auth = data.auth; }, }; export const getters = { isAuthenticated: state => !!state.user || !!sessionStorage.getItem("user"), }; export default { state, getters, actions, mutations, namespaced: true, };
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51看來看去,最主要的問題是, state的型別沒有宣告,所以我們改成這樣:
typescript// user.ts // 把使用者權限列舉起來 enum PERMISSION_LEVEL { TOP_MANAGEMENT, // 0 最高管理者 全開 MANAGER, // 1 網站管理者 USER, // 2 一般使用者 VISITOR // 3 訪客 } // 宣告、並匯出user的State export interface iUserState { isLogin: Boolean, // 是否有登入 jwtToken: string, userData: { user: string, name: string, auth: PERMISSION_LEVEL, }, } export default { namespaced: true, state: { isLogin: false, jwtToken: '', userData: { user: '', name: '', auth: PERMISSION_LEVEL.VISITOR, }, }, // 把state通通補上型別 mutations: { // 同步 signIn(state: iUserState) { state.isLogin = true; }, signOut(state: iUserState) { state.isLogin = false; }, /** 將登入後的 Token 轉 成userData * @param {*} state * @param {JWT} JWT */ setUser(state: iUserState, JWT: string) { state.jwtToken = JWT; // JWT = header.payload.Signature const Token = JWT.split("."); // 解析使用者資料 const data = JSON.parse(Base64.decode(Token[1])); // 記錄登入者資訊 state.userData.user = data.user; state.userData.name = data.name; state.userData.auth = data.auth; }, }, getters: { // 這邊順便被提醒state.user 不存在,把userData補上去。 isAuthenticated: (state: iUserState) => !!state.userData.user || !!sessionStorage.getItem("user"), } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56然後安裝一下:
js-base64
JWT機制,解碼用的:shellyarn add js-base64 -D
1由於
js-base64
已經自帶.d.ts
了, 所以你啥都不用做就可以直接用了。 剛改寫第一支JS程式,馬上就體驗到TS的好用與方便。route.js
的改寫方式大同小異,這邊就省略掉了。2. index.js
modules都改寫完之後,把昨天調整過的
src/store/index.js
改成這樣:typescriptimport { InjectionKey } from 'vue' import { createStore, useStore as baseUseStore, Store } from 'vuex' import { iRouteState } from './modules/route'; // 路由相關 import { iUserState } from './modules/user'; // 登入、使用者相關 export interface State { route: iRouteState, user: iUserState, } // 全部模組導入 let modules = {} const modulesFiles = import.meta.glob("./modules/*.ts", { eager: true, import: 'default' }); for (const path in modulesFiles) { const moduleName = path.replace(/(.*\/)*([^.]+).*/gi, '$2'); console.log(modulesFiles); modules = { ...modules, [moduleName]: modulesFiles[path] } } export const key: InjectionKey<Store<State>> = Symbol() export const store = createStore<State>({ modules }) // 定義自己的 `useStore` composition(組合式) API export function useStore() { return baseUseStore(key) }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31這樣就大功告成啦~
小結:
實際使用TypeScript改寫JS, 發現好像沒有想像中的難, 有一種用實際的程式碼寫註解的既視感, 好像可以繼續改寫下去,有完賽的可能性ㄟ!!