不太一样的前端开发之TypeScript装饰器和面向对象

1、前言

早前的一些文章中提到的我们在前端使用TypeScript装饰器和面向对象设计的方案作为日常的业务开发方式,引来了不少的争议和讨论,虽然我们也使用了Hooks来实现一些视图层公共代码的抽离,但我们依然还是坚持在项目中使用一些强面向对象的设计思维, 今天我们来仔细聊聊。

2、面向对象

我们使用面向对象的开发方式主要体现在以下几个方面:

2.1 公共代码的继承

在日常开发中经常存在一些公共代码或属性,如数据转换、数据拷贝、数据过滤、公共的属性(ID、创建时间)等,我们需要对它们进行抽离,虽然像 interface type 等都能完成一些公共属性的声明和继承,使用一些方法类可以将一些公共的方法进行封装,但从抽象上来说,放到 class 中也许更合适:

类的对象更抽象

使用 interfacetype 定义数据结构虽然没问题,但实际传递的参数还是个简单类型的对象Object,无法包含一些自定义的方法,而且无法通过数据取得对应的定义类型,无法实现类似 反射 获取一些特性数据。

typescript 复制代码
interface IBase{
	id: number
}
interface IUser extends IBase{
	nickname: string
}

const user: IUser = {nickname: "Hamm"}

使用 class 定义数据类型,可以解决上面的问题。

typescript 复制代码
class Base {
	id!: number
}
class User extends Base{
	nickname!: string
}

const user = new User()
user.id = 1
user.nickname = "Hamm"

// 当然 也可以使用一些构造或自定义方法来快速初始化数据 如
class BaseData{
	id!: number
	setId(id: number):this{
		this.id = id
		return this
	}
}
class User extends BaseData{
	nickname!: string
	setNickname(nickname: string): this{
		this.nickname = nickname
		return this
	}
	
	userType!: number
	
	isAdmin():boolean{
		if(this.userType === 1){
			return true
		}
		return false
	}
}

const user = new User().setId(1).setNickname("Hamm")

上面的代码是不是看起来很多? 其实使用 TypeScriptvscode 写的时候,很多都是直接用 . 给选出来的,类的声明也可以使用一些工具来自动生成,如 Json转TS代码工具

无需将方法和属性分开

上面的示例中,传递的 user 对象就是正经的一个用户对象了,包含了用户的一些属性和方法,方便了下面的使用:

typescript 复制代码
user.isAdmin() // 直接返回是否管理员的 `true` `false`

2.2 相似代码的抽象

相似代码的抽象,在后端会经常用到,在前端的也是如此,大部分业务都相同,有部分相似但又有一些小区别,为了对这种场景进行封装,我们可以使用抽象类来处理。比如 声明了一个基础的 curd 接口请求方法:

typescript 复制代码
abstract class AbstractCurdApi<D extends BaseData>{
	// 获取请求的 baseUrl 每个子类不一样的地方
	abstract getBaseUrl(): string
	
	delete(): void{
		// 删除
	}
	
	add(data: D): D{
		// 新增一条
	}
	
	getById(id: number): D{
		// 查询指定ID的一个数据
	}
	
	// 其他curd方法
}

接下来需要使用的子类中就可以将需要自己实现的方法实现后即可继承父类的所有方法。

typescript 复制代码
class UserApi extends AbstractCurdApi<User>{
	getBaseUrl(){
		return 'user'
	}
}

当然,TypeScript 还有一个 Java 不服的地方,就是它竟然支持将属性抽象掉:

typescript 复制代码
abstract class AbstractCurdApi<D extends BaseData>{
	abstract baseUrl: string
}

2.3 类和属性可以挂载装饰器

因为类和属性都支持挂载装饰器,所以我们可以选择 class 类来封装数据结构,既可以为它实现一些方法,也可以对类和属性进行装饰,然后后续使用这些装饰配置来实现更多的功能。

请接着阅读下面关于装饰器的部分。

3. 装饰器

TypeScript 的装饰器和 Java 的注解类似,以 @ 开头,写在属性、方法、类的前面,关于装饰器的基础知识,可以参考官方文档,我们这里只讲如何使用:

typescript 复制代码
@Class("用户")
@Enable(CURD.ADD,CURD.DELETE)
class User{
	@Field("昵称")
	@Form({
		required:true,
		placeholder:" 请输入一个牛逼的名字"
		// ...
	})
	@Table({
		copy: true, //表格中显示为一个可复制的单元格
		align: "left",
		// ...
	})
	nickname!: string
	
	@Field("性别")
	@Dict(SexDictionary)
	@Search()
	sex!: Sex
}

如上,我们声明了一个 User 类,并装饰了一大堆的配置,比如表格、表单、搜索等等。

其他在使用的组件中,就可以直接传入这个类,然后获取类中配置的一些信息,来渲染不同的表格、表单、搜索等状态。

如此使用之后,可以直接在类中完成集中化的配置。装饰器的玩法还有很多,听舒服的。

4. 最后

文中说到的一些东西,目前都可以在我们的开源仓库中看到所有代码:

Github:github.com/HammCn/AirP...

你也可以查看我的专栏: 用TypeScript写前端

相关推荐
GIS开发特训营1 分钟前
Vue零基础教程|从前端框架到GIS开发系列课程(七)响应式系统介绍
前端·vue.js·前端框架·gis开发·webgis·三维gis
Cachel wood27 分钟前
python round四舍五入和decimal库精确四舍五入
java·linux·前端·数据库·vue.js·python·前端框架
学代码的小前端29 分钟前
0基础学前端-----CSS DAY9
前端·css
joan_8533 分钟前
layui表格templet图片渲染--模板字符串和字符串拼接
前端·javascript·layui
m0_748236111 小时前
Calcite Web 项目常见问题解决方案
开发语言·前端·rust
Watermelo6171 小时前
详解js柯里化原理及用法,探究柯里化在Redux Selector 的场景模拟、构建复杂的数据流管道、优化深度嵌套函数中的精妙应用
开发语言·前端·javascript·算法·数据挖掘·数据分析·ecmascript
m0_748248941 小时前
HTML5系列(11)-- Web 无障碍开发指南
前端·html·html5
m0_748235611 小时前
从零开始学前端之HTML(三)
前端·html
一个处女座的程序猿O(∩_∩)O3 小时前
小型 Vue 项目,该不该用 Pinia 、Vuex呢?
前端·javascript·vue.js
hackeroink6 小时前
【2024版】最新推荐好用的XSS漏洞扫描利用工具_xss扫描工具
前端·xss