TypeScript装饰器实践
·
2 min read
当前装饰器还只是ES提案[Stage 2],在过去,还没定下来的东西,我们无话可说。但今天,项目中使用的是TypeScript,Babel,本身存在转译,所以我们往往可以用些超越当前的特性。比如Angular2框架中就有装饰器的大量存在。
这块之前我也只是在NG中较多的使用,并不算熟悉,于是冲下电。
装饰器
装饰器模式,顾名思义,就是将某个类重新装扮下,使它在功能上更强 大,但是作为原来的这个类,使用者不应该感受到装饰前与装饰后有什么 不同,否则就破坏了原有类的结构,所以装饰器模式要做到对装饰类的使 用者透明
类别
- 类装饰器
- 方法装饰器
- 访问器装饰器
- 属性装饰器
- 参数装饰器
- 元数据装饰器
要知道
- 装饰器本质是
函数
- TS中装饰器的使用
只能围绕着类,类属性方法等使用
,枚举类型,常量,方法不可
举例子
属性装饰器
修改目标属性值
function modifyProp(target: any, propertyKey: string) {
target[propertyKey] = Math.random().toString();
}
类装饰器
修改类中所有属性值
function modifyProps(prefix: string) {
return (constructor: any) => {
Object.keys(constructor).forEach(
item => constructor[item] = prefix + item)
return constructor;
}
}
其它类别例子,自行再查。
配置
为了使用装饰器,需要配置下构建工具。我的项目中用到了TypeScript及Babel,所以进行如下配置。
install package
$ yarn add @babel/plugin-proposal-decorators -d
tsconfig.json
"experimentalDecorators": true,
/* Enables experimental support for ES7 decorators. */
"emitDecoratorMetadata": true,
/* Enables experimental support for emitting type metadata for decorators. */
注意
- 装饰器有用到reflect-metadata,再开启emitDecoratorMetadata设定
babel.config.js
注意顺序,该插件放在第一位。
plugins: [
['@babel/plugin-proposal-decorators', { 'legacy': true }]
]
浏览器兼容性
- 如上所说,装饰器只是个函数,可以理解为是语法糖,Babel转译还是会将其变成一般的函数,所以并不会因此而带来兼容性上的改变
小试牛刀
当前从事的项目中actiontype的定义如下,你会发现变量名称与内容严格的存在重复,so,采用类装饰器来改造下。对比如下
import { createActionPrefix } from 'redux-actions-helper';
const prefixCreator = createActionPrefix('USER');
export default class UserActionTypes {
static INIT_USER = prefixCreator('INIT_USER');
static SET_BUSINESS_UNIT = prefixCreator('SET_BUSINESS_UNIT');
}
import { createActionPrefix } from 'redux-actions-helper';
@actionTypes('USER')
export default class UserActionTypes {
static INIT_USER = null;
static SET_BUSINESS_UNIT = null;
}
export function actionTypes(prefix: string) {
return (constructor: any) => {
Object.keys(constructor).forEach(item => (constructor[item] = createActionPrefix(prefix)(item)));
return constructor;
};
}
写在最后
装饰器谈不上多强大,本质是个函数,但换个角度理解它,会体会到是一种设计模式,使用方式,而这种形态是不侵入你本身设计的类,属性的。so,理解这点,才可以更好更合适的使用。