zoukankan      html  css  js  c++  java
  • TypeScript入门笔记(五)

    上篇。

    这篇主要记录TypeScript中的几种装饰器的概念与用法。装饰器(Decorators):用一种特性标注的写法作为声明,能够给类,方法,属性扩展功能,可以简单地理解为是非侵入式的行为修改。分为:类装饰器、方法装饰器、属性装饰器、访问器装饰器、参数装饰器。

    类装饰器

     1 /**
     2  * 装饰器(Decorators):用一种特性标注的写法作为声明,能够给类,方法,属性扩展功能,可以简单地理解为是非侵入式的行为修改
     3  * 分为:类装饰器、方法装饰器、属性装饰器、访问器装饰器、参数装饰器
     4  * 注:在tsconfig.json中将打开 “"experimentalDecorators": true” 以启用装饰器功能
     5  */
     6 
     7 /* ****************************类装饰器******************************* */
     8 //以下这个Person类使用了装饰器“yasuo”
     9 //@yasuo
    10 class Person {
    11     roleLine: string | undefined;
    12 
    13     constructor(readonly name: string, readonly birthDay: Date) {
    14         this.roleLine = "Hello everyone"
    15     }
    16 
    17     SayHi(): void {
    18         console.log(this.roleLine);
    19     }
    20 }
    21 
    22 /**
    23  * 装饰器其实也是一个方法,装饰器中可以做的事有三:
    24  * (1)做点自己想做的事
    25  * (2)扩展属性或者方法
    26  * (3)重载类的构造函数
    27  */
    28 
    29 //参数target便代表Person类(的构造器)
    30 function yasuo(target: any) {
    31     //(1)只要有类应用了这个装饰器,便会执行
    32     console.log("Follow the wind, but watch your back.")
    33 
    34     //(2)为Person类扩展一个Attach的方法
    35     target.prototype.Attack = function () {
    36         console.log("Hasaki!");
    37     }
    38 
    39     //(3)重载构造函数
    40     return class extends target {
    41         roleLine: any = "Make it quick."
    42     }
    43 }
    44 //这里指定为any类型是为了防止调用扩展方法Attack时TypeScript编译器报错
    45 let hero: any = new Person("yasuo", new Date("2013-12-14"));
    46 
    47 hero.SayHi();   // 控制台输出:Make it quick.
    48 //hero.Attack()   // 控制台输出:Hasaki!
    49 
    50 
    51 /* ****************************装饰器工厂****************************** */
    52 // 带参数的装饰器
    53 @skin("黑夜使者")
    54 class Hero {
    55     roleLine: string | undefined;
    56 
    57     constructor(readonly name: string, readonly birthDay: Date) {
    58         this.roleLine = "welcome to LOL"
    59     }
    60 
    61     SayHi(): void {
    62         console.log(this.roleLine);
    63     }
    64 }
    65 //定义“装饰器工厂”
    66 function skin(value: string) {      // 这是一个装饰器工厂
    67     return function (target: any) {      //  这是装饰器
    68         let line: string;
    69         switch (value) {
    70             case "黑夜使者":
    71                 line = "我是变革之风"
    72                 break;
    73             case "猩红之月":
    74                 line = "Hasaki"
    75                 break;
    76             default:
    77                 line = "Attack"
    78                 break;
    79         }
    80 
    81         target.prototype.Attack = function () {
    82             console.log(line);
    83         }
    84     }
    85 }
    86 
    87 let h1: any = new Hero("yasuo", new Date("2013-12-14"));
    88 h1.Attack();    //控制台输出:我是变革之风

    属性装饰器

     1 /* ****************************属性装饰器****************************** */
     2 // 属性装饰器接收两个参数
     3 // 参数一:对于静态成员是构造器,对于实例成员是类的原型对象
     4 // 参数二:属性的名称
     5 
     6 class Hero {
     7 
     8     @lineInjection("Hasaki")    //使用装饰器为其赋值
     9     roleLine: string | undefined;
    10 
    11     constructor(readonly name: string, readonly birthDay: Date) {
    12     }
    13 
    14     SayHi(): void {
    15         console.log(this.roleLine);
    16     }
    17 }
    18 
    19 //定义一个属性装饰器
    20 function lineInjection(line: string) {      //装饰器的参数
    21     return function (target: any, prop: any) {
    22         target[prop] = line;
    23     }
    24 }
    25 
    26 let h1 = new Hero("yasuo", new Date("2013-12-14"));
    27 h1.SayHi();     //控制台输出:Hasaki

    方法装饰器

     1 /* ****************************方法装饰器****************************** */
     2 // 用于监视,修改方法,接受3个参数
     3 // 参数一:对于静态成员是构造器,对于实例成员是类的原型对象
     4 // 参数二:方法的名称
     5 // 参数三:方法的属性描述符,其中value属性就是当前方法的定义
     6 
     7 class Person {
     8     constructor(public firstName: string, public lastName: string) { }
     9 
    10     @useFullName
    11     public SayHi(): void {
    12         console.log(`i am ${this.firstName}`);
    13     }
    14 }
    15 
    16 //定义一个方法装饰器,修改方法,让其输出全名
    17 function useFullName(
    18     target: object,         //参数一:类的原型对象
    19     propertyName: string,   //参数二:成员的名称
    20     descriptor: PropertyDescriptor  //参数三:成员的描述信息
    21 ): void {
    22 
    23     //将改写前的原方法暂存下来
    24     const sayLastName: Function = descriptor.value;
    25 
    26     //改写方法
    27     descriptor.value = function () {
    28         //先调用一次原方法
    29         sayLastName.call(this);
    30         //再输出一次全名
    31         console.log(`${this.firstName} ${this.lastName}`)
    32     };
    33 }
    34 
    35 let mj = new Person("bond", "james");
    36 
    37 mj.SayHi();     //控制台输出:i am bond
    38                 //bond james

    方法参数装饰器

     1 /* ****************************方法参数装饰器****************************** */
     2 // 可以用来监视方法传入的参数
     3 // 和之前几个装饰器类似,接受的参数如下
     4 // 参数一:对于静态成员是构造器,对于实例成员是类的原型对象
     5 // 参数二:方法的名称
     6 // 参数三:参数在方法中的位置(index)
     7 
     8 class Greeter {
     9     greeting: string;
    10 
    11     constructor(message: string) {
    12         this.greeting = message;
    13     }
    14 
    15     greet(@log name: string) {
    16         return "Hello " + name + ", " + this.greeting;
    17     }
    18 }
    19 
    20 function log(
    21     target: Object,
    22     propertyKey: string,
    23     parameterIndex: number) {
    24 
    25     console.log(target);
    26     console.log(propertyKey);
    27     console.log(parameterIndex);
    28 }

    装饰器的执行顺序

    如果一个对象中包含多个装饰器,如

    1 @f
    2 @g
    3 class x

    那么他的执行顺序是f(g(x)),先执行下面的装饰器后再执行上面的。

    若多种装饰器共存是,其执行顺序是:属性装饰器 → 方法装饰器 → 方法参数装饰器 → 类装饰器。

  • 相关阅读:
    《大数据——大价值、大机遇、大变革》试读
    div+csS中的一些技巧和浏览器兼容的办法
    js正则表达式
    布局 IE haslayout
    几个好的网站
    ie6 几个li上下排列会闪动的问题,嵌套div—外层div内层div都设置背景颜色,内层div背景色不显示的问题
    live()解决Jquery采用append添加的元素事件无效和获取不到添加元素的值
    SQL语句写返回一天内的纪录,得到一周内星期几的时间
    网易邮箱添加附件功能原理浅析转
    实体类序列化
  • 原文地址:https://www.cnblogs.com/xhy0826/p/12807766.html
Copyright © 2011-2022 走看看