装饰器
概括
装饰器是一种特殊类型 的声明,它能被附加到类、方法、访问器、属性、或参数上,用@添加 目前TS中依旧为一个测试中的版本 ,若要启用实验性的装饰器特性 ,需要在命令行或tsconfig.json 里面启用experimentalDecorators编译器选项
类的装饰器
类装饰器 就是在类声明之前被声明类装饰器 被应用于类的构造函数 ,可以用来观察 、修改 或替换 类定义类装饰器 不能用来声明文件中(.d.ts),也不能用在任何外部上下文中(比如declare的类)类装饰器 表达式会在运行时当作函数被调用,类的构造函数作为其唯一的参数 如果类装饰器返回一个值,它会使用提供的构造函数 来替换类的声明
类装饰器的基本认识
function testDecorator ( constructor: any ) {
constructor. prototype. uname = "法外狂徒张三"
constructor. prototype. show = ( ) : void => {
console . log ( "类装饰器" )
}
}
@ testDecorator
class Person {
}
let person = new Person ( ) ;
( person as any ) . show ( )
类装饰器添加参数
function testDecorator ( flag: boolean ) {
if ( flag) {
return function ( constructor: any ) {
constructor. prototype. uname = "法外狂徒张三"
constructor. prototype. show = ( ) : void => {
console . log ( "类装饰器" )
}
}
} else {
return function ( constructor: any ) {
constructor. prototype. show = ( ) : void => {
console . log ( ` 我的名字叫 ${ constructor. prototype. uname} ` )
}
}
}
}
@ testDecorator ( true )
class Person {
}
let person = new Person ( ) ;
( person as any ) . show ( )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
类装饰器中利用泛型
function testDecorator< T extends new ( ... args: any [ ] ) => { } > ( constructor: any ) {
return class extends constructor{
name = "法外狂徒张三"
age = 18
show ( ) {
console . log ( this . name)
}
}
}
@ testDecorator
class Person {
name: string
constructor ( uname: string ) {
this . name = uname
}
}
let person = new Person ( '富甲一方赵六' )
console . log ( person) ;
( person as any ) . show ( )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
类装饰器的使用
function testDecorator ( ) {
return function < T extends new ( ... args: any [ ] ) => { } > ( constructor: T ) {
return class extends constructor{
name = "法外狂徒张三"
age = 18
show ( ) {
console . log ( this . name)
}
}
}
}
const Person = testDecorator ( ) (
class {
name: string
constructor ( uname: string ) {
this . name = uname
}
}
)
let person = new Person ( '富甲一方赵六' )
console . log ( person) ;
person. show ( )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
方法装饰器
方法装饰器的概述
方法装饰器 写在一个方法的声明之前方法装饰器 可以用来监视 、修改 或替换 方法方法装饰器表达式会在运行时,当作函数被调用,传入下列三个参数
静态成员的类的构造函数 或实例成员的类的原型 成员的名称 该成员的属性描述符
function getNameDecorator ( target: any , key: string , desciptor: PropertyDescriptor) {
desciptor. value = function ( ) {
return "desciptor"
}
}
class Test {
name: string = "法外狂徒张三"
constructor ( uname: string ) {
this . name = uname
}
@ getNameDecorator
getName ( ) {
return this . name
}
static show ( ) : void {
console . log ( ` 他的描述 ${ this . name} ` )
}
}
let test = new Test ( '张三' )
console . log ( test. getName ( ) )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
访问器的装饰器
访问器的装饰器概述
访问器装饰器 声明在一个访问器的声明之前(紧靠着访问器声明)访问器装饰器 应用于访问器的属性描述并且可以用来监视 、修改 或替换 一个访问器的定义访问器装饰器 不能用在声明文件(.d.ts)或任何外部上下文(比如declare的类)里访问器装饰器表达式 会在运行时当作函数被调用,传入3个参数 :
对于静态成员来说是类的构造函数 ,对于实例成员是类的原型对象 成员的名字 描述对象 ts不允许同时装饰一个成员的get 和set访问器
function visitDecorator ( target: any , key: string , desciptor: PropertyDescriptor) {
desciptor. writable = false
}
class Test {
private _name: string
constructor ( uname: string ) {
this . _name = uname
}
@ visitDecorator
get name ( ) {
return this . _name
}
set name ( userName: string ) {
this . _name = userName
}
}
const test = new Test ( '法外狂徒张三' )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
属性的装饰器
属性装饰器的概述
属性的装饰器 声明在一个属性的声明之前(紧靠着访问器声明)属性的装饰器 应用于属性描述并且可以用来监视 、修改 或替换 一个访问器的定义属性的饰器 不能用在声明文件(.d.ts)或任何外部上下文(比如declare的类)里属性的装饰器表达式 会在运行时当作函数被调用,传入2个参数 :
对于静态成员来说是类的构造函数 ,对于实例成员是类的原型对象 成员的名字
属性装饰器的基本使用
function nameDecorator ( target: any , key: string ) {
}
class Test {
@ nameDecorator
name: string = "法外狂徒张三"
}
let test = new Test ( )
console . log ( test. name)
属性装饰器的进阶使用
function nameDecorator ( target: any , key: string ) : any {
const desciptor: PropertyDescriptor = {
writable: false
}
return desciptor
target[ key] = "权倾朝野王五"
}
class Test {
@ nameDecorator
name: string = "法外狂徒张三"
}
let test = new Test ( )
console . log ( test. name)
console . log ( ( test as any ) . _proto_. name)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
参数装饰器
参数装饰器的概述
参数装饰器 声明在一个参数声明之前(紧靠着访问器声明)参数装饰器 用于类构造函数或方法声明参数装饰器 不能用在声明文件(.d.ts),重载或任何外部上下文(比如declare的类)里参数装饰器表达式 会在运行时当作函数被调用,传入3个参数 :
对于静态成员来说是当前类 ,对于实例成员是当前实例 参数所在的方法名称 参数在参数列表中的索引
function paramDecorator ( target: any , key: string , index: number ) {
}
class Test {
getInfo ( @ paramDecorator name: string , age: number ) {
console . log ( name, age)
}
}
let test = new Test ( )
test. getInfo ( "法外狂徒张三" , 20 )
案例
方法装饰器—问题
function catchErrorDecorator ( target: any , key: string , desciptor: PropertyDescriptor) {
const fn = desciptor. value
desciptor. value = function ( ) {
try {
fn ( )
} catch ( e) {
console . log ( "userInfo上不存在该属性" )
}
}
}
const userInfo: any = undefined
class Test {
@ catchErrorDecorator
getName ( ) {
return userInfo. name
}
@ catchErrorDecorator
getAge ( ) {
return userInfo. age
}
}
const test = new Test ( )
test. getName ( )
test. getAge ( )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
方法装饰器—工厂模式解决wenti
function catchErrorDecorator ( msg: string ) {
return function ( target: any , key: string , desciptor: PropertyDescriptor) {
const fn = desciptor. value
desciptor. value = ( ) => {
try {
fn ( )
} catch ( e) {
console . log ( msg)
}
}
}
}
const userInfo: any = undefined
class Test {
@ catchErrorDecorator ( "userInfo.name 不存在" )
getName ( ) {
return userInfo. name
}
@ catchErrorDecorator ( "userInfo.age 不存在" )
getAge ( ) {
return userInfo. age
}
}
const test = new Test ( )
test. getName ( )
test. getAge ( )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29