拋棄vuex ,擁抱ts,手擼泛型Store

前段時間學習了下vue3 和ts ,就嘗試下做了個項目,結果發現vuex和ts幾乎無法結合,越寫越彆扭,開始懷疑用ts就是自己給自己挖坑,然後加了幾個vue相關的群,去抱怨了幾句,得到大佬指點:你可以不用vuex!

對,我可以不用vuex,然後嘗試實現了一個自己的store ,本人雖然前端是個小白,但c#還是寫了五六年,對泛型還是比較熟悉的,寫完之後對ts大愛。不多說了 上程式碼:

 Store基類程式碼如下  :

base-store.ts  

 1 import BaseEntity from '@/entities/base-entity'
 2 import PageResult from '@/entities/page-result'
 3 import { readonly } from '@vue/reactivity'
 4 
 5 export default abstract class BaseStore<T extends BaseEntity> {
 6   protected url = ''
 7   protected _all: T[] = []
 8   public get all() {
 9     return readonly(this._all)
10   }
11 
12   protected _list: T[] = []
13   public get list() {
14     return readonly(this._list)
15   }
16 
17   protected _editItem: T | undefined
18   public get editItem() {
19     return this._editItem
20   }
21   public set editItem(val: T | undefined) {
22     this._editItem = val
23   }
24 
25   protected _currentPage = 1
26   public get currentPage() {
27     return this._currentPage
28   }
29   public set currentPage(val) {
30     this._currentPage = val
31   }
32 
33   protected _pageSize = 30
34   public get pageSize() {
35     return this._pageSize
36   }
37   public set pageSize(val) {
38     this._pageSize = val
39   }
40 
41   protected _totalCount = 0
42   public get totalCount() {
43     return this._totalCount
44   }
45 
46   protected _loading = false
47   public get loading() {
48     return this._loading
49   }
50 
51   async getAll() {
52     const response = await window.ajax.get(`/api/admin/${this.url}/getall`)
53     this._all = response.data
54   }
55   async get(query: any) {
56     this._loading = true
57     const response = await window.ajax.get(`/api/admin/${this.url}`, { params: query })
58     this._loading = false
59     const page = response.data as PageResult<T>
60     this._totalCount = page.totalCount
61     this._list = page.items
62   }
63   async getById(id: string | number) {
64     const response = await window.ajax.get(`/api/admin/${this.url}/${id}`)
65     return response.data
66   }
67   async create(payload: T) {
68     await window.ajax.post(`/api/admin/${this.url}`, payload)
69   }
70   async update(payload: T) {
71     await window.ajax.put(`/api/admin/${this.url}`, payload)
72   }
73   async delete(id: string | number) {
74     await window.ajax.delete(`/api/admin/${this.url}/${id}`)
75   }
76 }

上面程式碼中包含了 基本的curd操作 ,和數據的存儲(欄位屬性),不能在外部讀取的欄位 只需要設置get就行了 ,可以讀寫的設置 get set

上面程式碼中用到了BaseEntity 和PageResult 兩個類型 程式碼如下

 

base-entiy.ts

1 export default interface BaseEntity {
2   id: number | string
3   createTime: Date
4   createUserId: number
5   updateTime: Date
6   updateUserId: number
7 }

page-result.ts

export default class PageResult<T> {
  items: T[] = []
  totalCount: number = 0
}

作為子類 ,只需要繼承基類就可以了 無需多餘程式碼,比如下面的 UserStore

user-store.ts

import { reactive } from 'vue'
import User from '../entities/user'
import BaseStore from './base-store'
class UserStore<T> extends BaseStore<User> {
  url = 'user'
}

export default reactive(new UserStore())

上面只需要這幾行程式碼就實現了完整的的user的curd  ,還包括分頁等操作,程式碼量大大減少,同樣的方法可以實現TeacherStore, StudentStore…… 

如果基類的方法不能滿足業主需求,子類裡面可以加入自己特定方法

導出store包裹一層reactive變成代理對象, 可以響應ui介面

實體類 User程式碼如下

user.ts

import BaseEntity from './base-entity'

export default interface User extends BaseEntity {
  id:number
  password: string
  name: string
  phone:string
  email:string
}

 

這樣使用store的話就很簡單了,就像下面的程式碼

import userStore from '@/store/user-store'

userStore.getAll()

const list=userStore.list

userStore.eidtItem=list[0]

這樣的好處就是全部都是強類型,寫程式碼的時候有智慧提示,書寫錯誤編譯不通過!不像之前vuex,寫起來太難了

 

像一般後台管理網站,最基本就是 一個列表頁面 一個新增對話框 一個修改對話框 ,這樣我們還可以進一步去抽象, 提取公共的方法、欄位,進一步去減少程式碼量。比如實現 ListViewModel<T>  CreateViewModel<T>  EditViewModel<T>   這裡就不再寫了