拋棄vuex ,擁抱ts,手擼泛型Store!
- 2021 年 4 月 27 日
- 筆記
- ts vue store vuex 泛型
前段時間學習了下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> 這裡就不再寫了