前段时间学习了下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> 这里就不再写了