不太一样的前端开发之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写前端

相关推荐
IT_陈寒9 分钟前
Java性能优化:从这8个关键指标开始,让你的应用提速50%
前端·人工智能·后端
天生我材必有用_吴用11 分钟前
Vue3+Node.js 实现大文件上传:断点续传、秒传、分片上传完整教程(含源码)
前端
摸鱼的春哥27 分钟前
前端程序员最讨厌的10件事
前端·javascript·后端
牧羊狼的狼4 小时前
React 中的 HOC 和 Hooks
前端·javascript·react.js·hooks·高阶组件·hoc
知识分享小能手6 小时前
React学习教程,从入门到精通, React 属性(Props)语法知识点与案例详解(14)
前端·javascript·vue.js·学习·react.js·vue·react
魔云连洲6 小时前
深入解析:Vue与React的异步批处理更新机制
前端·vue.js·react.js
mCell6 小时前
JavaScript 的多线程能力:Worker
前端·javascript·浏览器
超级无敌攻城狮8 小时前
3 分钟学会!波浪文字动画超详细教程,从 0 到 1 实现「思考中 / 加载中」高级效果
前端
excel9 小时前
用 TensorFlow.js Node 实现猫图像识别(教学版逐步分解)
前端
前端工作日常9 小时前
我学习到的Vue2.6的prop修饰符
vue.js