Typescript(更新中)

ts

概述

ts相比js优势

  • js的超集
  • 类型化:更容易发现类型错误
  • 提高了代码的可读性 更容易重构与维护
  • 补充了接口 枚举等大型项目js缺失的功能

第一个ts文件

  • ts转换js :执行tsc hello.ts
    node hello.js

  • 简化执行ts:使用ts-node包
    安装:npm i -g ts-node
    使用:ts-node hello.ts执行ts文件

  • cd到目录下;tsc --init生成tsconfig.json 更改"outdir":“./js" 点击终端 运行任务 点击typescript 点击tsc监视

  • 注释和输出语句

    • 单行注释:// 多行注释/**/
    • 输出语句:console.log();
  • 变量和数据类型

    • 声明变量并指定类型 let age :number;
    • 变量赋值 age=18;
  • 类型注解

    • :number
  • 变量的命名规则

    • 只能出现字母数字下划线美元符号开头 并且不能以数字开头
    • 严格区分大小写

数据类型、函数

数据类型

  • number string boolean undefined null

  • number 包括整数值和浮点数据类型(或正数和负数)

  • string 字符串类型 单引号/双引号内

  • Boolean 用来表示真或假 0或1 true或false

  • undefined null 类型的值和类型本身一样 一个元素可以设置多个类型 var num:number|null|undefined;

  • 数组类型

    • let arr : number[]=[1,2,3,4]
      let arr : string[]=[‘string’ , ‘js’]

    • let arr:Array=[12,123,555,25]

    • 元组类型tuple (属于数组的一种)

      • let arr: [string,number,boolean]= [“ts”,3,18,true]
  • 枚举类型(用于标识类型)

    • enum 枚举名{
      标识符[=整型常数],
      标识符[=整型常数],
      ……
      标识符[=整型常数],
      };

    • enum Flag {
      success=1,
      error=-1
      }
      var f:Flag=Flag.success

  • 任意类型 any

    • 用处:getElementById
  • nerver类型

    • 是其他类型(包括null和undefined)的子 代表从不会出现的值
  • 函数类型

    • void()表示方法没有返回任何类型
    • 如果方法有返回值 返回什么类型 指定什么类型

函数

  • 函数的定义

    • es5中的定义方法

    • ts中定义函数的方法

      • 函数声明法

        • function run(): string {
          return ‘string’;
          }
        • function getInfo(name: string, age: number): string {
          return ‘${name} ${age}’
          }
      • 匿名函数法

        • var fun2 = function (): number {
          return 123;
          }
        • var getInfo = function (name: string, age: number): string {
          return ‘${name} ${age}’
          }
      • 没有返回值的方法

        • function run(): void {
          console.log(“123”);
          }
      • 可选参数

        • es5中方法的实参和形参可以不一样 ts中必须一样 如果不一样需要配置可选参数
          可选参数必须配置到参数的最后面
        • function getInfo(name: string, age?: number): string {
          if (age) {
          return ‘${name} KaTeX parse error: Expected 'EOF', got '}' at position 9: {age}'; }̲ else { return …{name} 年龄保密’;
          }
          }
      • 默认参数

        • es5中无法设置默认参数 在es6和ts中可以配置默认参数
        • function getInfo(name: string = 20, age: number): string {
          return ‘${name} ${age}’
          }
      • 剩余参数

        • function sum(…result: number[]): number {
          var sum = 0;
          for (car i = 0; i < result.length; i++) {
          sum + =result[i];
          }
          }
      • 函数重载

        • function getInfo(num: number): number
          function getInfo(num: any): any {
          if (typeof str === 'string') {
          return '我叫,' + Str;
            } else {
              return '我的年龄是' + Str;
            }
          }
          
        • function getInfo(name: string, age: number): string;
          function getInfo(name: any, age?: any): any {
            if (age) {
              return '我叫,' + name + '我的年龄是' + age;
            } else {
              return '我叫' + name;
            }
          }
          
      • 箭头函数

        • setTimeout(() => {
          alert(‘run’)
          }, 1000);
        • 箭头函数中的this指向上下文

ES5中的类

  • es5中通过构造函数和原型链来继承方法
    es5中的继承 通过原型链加对象冒充继承
    call()方法
    Web.prototype=new Person();
  • 实例方法:new后才能调用 静态方法 直接就能执行

TS中的类

  • class Person {
    name: string;//属性 前面省略了public关键字
    constructor(name: string) {//构造函数 实例化类时触发的方法
      this.name = name;
    }
    getName(): string {
      return this.name;
    }
    setName(): void {
      this.name = name;
    }
    run() {
      alert(this.name);
    }
    }
    var p = new Person('张三');
    alert(p.getName());
    
  • ts中实现继承

    • class Person {
        name: string;
        constructor(name: string) {
          this.name = name;
        }
        run(): string {
          return '${this.name}在运动';
        }
      }
      var p = new Person('王五');
      p.run();
      
      class Web extends Person {
        constructor(name: string) {
          super(name);
        }
      }
      var w = new Web('李四');
      alert(w.run());
      
  • 类里面的修饰符

  • typescript里面定义属性时给我们提供了三种修饰符 public protected private

  • 静态属性、静态方法

    • function Person() {
        this.run1 = function () {
      
        }
      }
      Person.name = 'haha';
      Person.run2 = function () {
        // 静态方法
      }
      var p = new Person();
      Person.run2();//静态方法的调用
      
    • ts中静态方法

      class Person {
        public name: string;
        public age: number = 20;
        static sex = '男';
        constructor(name: string) {
          this.name = name;
        }
        run() {//实例方法
          alert('${this.name}在运动')
        }
        work() {
          alert('${this.name}在工作')
        }
        static print() {//静态方法 在静态方法中没法调用类里面的属性 可以调用静态属性
          alert('print方法')
        }
      }
      Person.print()
      
  • 多态

    • 父类定义一个方法不去实现,让继承它的子类去实现 每一个子类有不同的表现

    • 多态属于继承

    • class Animal {
        name: string;
        constructor(name: string) {
          this.name = name;
        }
        eat() {//具体吃什么 不知道 由他的子类实现 每个子类的表现不一样
          console.log('吃的方法');
        }
      }
      
      class Dog extends Animal {
        constructor(name: string) {
          super(name)
        }
        eat() {
          return this.name + '吃肉'
        }
      }
      
      class Cat extends Animal {
        constructor(name: string) {
          super(name)
        }
        eat() {
          return this.name + '吃老鼠'
        }
      }
      
  • 抽象类

    • ts中的抽象类 他是提供其他类继承的基类 不能直接实例化

    • 用abscript关键字定义抽象类和抽象方法 抽象类中的抽象方法不包含具体实现并且必须在派生类中实现

    • abscript抽象方法只能放在抽象类里

    • 抽象类和抽象方法用来定义标准 标准animal这个类要求他的子类必须包含eat方法

    • abscript class Animal {
        public name: string;
        constructor(name: string) {
          this.name = name;
        }
        abstract eat(): any;
      }
      //var a = new Animal()/*错误的方法 */
      calss Dog extends Animal{
        //抽象类的子类必须实现抽象类里面的抽象方法
        //其他方法可以不实现
        constructor(name: string){
          super(name)
        }
        eat(){
          console.log(this.name + '吃粮食');
        }
      }
      var d = new Dog('小黑');
      d.eat();
      

TS中的接口

  • 接口的作用 :在面向对象的编程中,接口是一种规范的定义 它定义了行为和动作的规范 在程序设计里面 接口起到一种限制和规范的作用 接口定义了某一批类需要遵守的规范 接口不关心这些类的内部状态数据 也不关心这些类里面的方法的实现细节 他只规定这批类里必须提供某些方法 提供这些方法的类就可以满足实际需要。typescript中的接口类似于Java同时还增加了更加灵活的接口类型 包括属性、函数、可索引和类等

  • 属性接口 -对json的约束

    • function printLabel(labelInfo: { label: string }): void {
        console.log('printlabel');
      }
      printLabel('haha');//错误写法
      printLabel({name:'张三'});//错误写法
      printLabel({label:'张三'});//正确写法
      
    • 接口:行为和动作的规范 对批量方法进行约束

      //就是传入对象的约束 属性接口
      interface FullName {
        firstName: string;
        secondName: string;
      }
      function printName(name: FullName) {
        //必须传入对象 firstName secondName
        console.log(name.firstName + "---" + name.secondName);
      }
      var obj = ({//传入的参数必须包含firstName和secondName
        age: 20,
        firstName: 'zhang',
        secondName: 'san'
      })
      printName(obj)
      
    • 接口 可选属性

      interface FullName {
        firstName: string;
        secondName?: string;//这时这个参数可传可不传
      }
      function getName(name: FullName) {
        console.log(name);
      }
      //参数的顺序可以不一样
      getName({
        secondName: 'secondname',
        firstName: 'firstname'
      })
      
      //原生js封装ajax请求
      interface Config {
        type: string;
        url: string;
        data?: string;
        dataType: string;
      }
      function ajax(config: Config) {
        var xhr = new XMLHttpRequest();
        xhr.open(config.type, config.url, true);
        xhr.send(config.data);
        xhr.onreadystatechange = function () {
          if (xhr.readyState == 4 && xhr.status == 200) {
            console.log('成功');
            if (config.dataType == 'json') {
              JSON.parse(xhr.responseText)
            } else {
              console.log(xhr.responseText);
            }
          }
        }
      }
      ajax({
        type: 'get',
        //data:'name:zhangsan',
        url: 'www.baidu.com',
        dataType: 'json',
      })
      
  • 函数类型接口:对方法传入的参数 以及返回值进行约束 批量约束

    • //加密的函数类型接口
      interface encrypt {
        (key: string, value: string): string;
      }
      var md5: encrypt = function (key: string, value: string): string {
        //模拟操作
        return key + value;
      }
      console.log(md5('name', 'zhangsan'));
      var sha1: encrypt = function (key: string, value: string): string {
        return 'key' + '---' + 'value';
      }
      console.log(sha1('name', 'lisi'))
      
  • 可索引接口 数组的约束、对象的约束(不常用)

    //ts中定义数组的方式
    // var arr:number[]=[2342,235325]
    // var arr1:Array<string>=['111','222']
    //对数组的约束 可索引
    interface UserArr {
      [index: number]: string;
    }
    var arr: UserArr = ['123124', '124124'];
    console.log(arr[0]);
    
    //可索引接口 对对象约束
    interface UserObj {
      [index: string]: string
    }
    var arr: UserObj = { name: '20' };
    
    //类类型接口 对类的约束 和 抽象类有点相似
    interface Animal {
      name: string;
      eat(str: string): void;
    }
    class Dog implements Animal {
      name: string;
      constructor(name: string) {
        this.name = name;
      }
      eat() {
        console.log(this.name + '吃粮食');
      }
    }
    var d = new Dog('xiaohei');
    d.eat()
    
  • 接口扩展 接口可以继承接口

    • interface Animal {
        eat(): void;
      }
      interface Person extends Animal {
        work(): void;
      }
      class Web implements Person {
        public name: string;
        constructor(name: string) {
          this.name = name;
        }
        eat() {
          console.log(this.name + '喜欢吃馒头');
        }
        work() {
          console.log(this.name + '写代码');
        }
      }
      var w = new Web('小关');
      w.work();
      
    • interface Animal {
        eat(): void;
      }
      interface Person extends Animal {
        work(): void;
      }
      class progrommer {
        public name: string;
        constructor(name: string) {
          this.name = name;
        }
        coding(code: string) {
          console.log(this.name + code);
        }
      }
      class Web extends progrommer implements Person {
        public name: string;
        constructor(name: string) {
          super(name)
        }
        eat() {
          console.log(this.name + '喜欢吃馒头');
        }
        work() {
          console.log(this.name + '写代码');
        }
      }
      var w = new Web('小关');
      w.work();
      w.coding('coding');
      

ts中的泛型

泛型定义

泛型 软件工程中 我们不仅要创建一致的定义良好的Api 同时也要考虑可重用性 组件不仅能够支持当前的数据类型 同时也能支持未来的数据类型 这在创建大型系统时为你提供了十分灵活的功能

在像C#和java这样的语言中,可以使用泛型来创建可重用的组件 一个组件可以支持多种类型的数据 这样用户就可以以自己的数据类型来使用组件

通俗理解 泛型就是解决来 接口 方法的复用性 以及对不特定数据类型的支持

泛型函数

function getData(value: string) {
  return value;//只能返回string类型的数据
}
//同时返回string类型 和number类型
function getData1(value: string) {
  return value;
}
function getData2(value: number) {
  return value;
}
//代码冗余

//使用any 类型 any可以解决这个问题 但any放弃了类型检查 传入什么 返回什么 传入的参数类型和返回的参数类型可以不一致
//例如传入number类型 必须返回number类型
function getData3(value: any): any {
  return value;
}

// 泛型可以支持不特定的数据类型 要求传入的参数和返回的参数类型一致
//T表示泛型 具体什么类型是调用这个方法的时候决定的
function getData4<T>(value: T): T {
  return value;
}
getData4<number>(123);
getData4<number>('123');//错误写法

泛型类

//泛型类:比如有个最小堆算法 需要同时支持返回数字和字符串两种类型 通过类的泛型来实现
class MinClass {
  public list: number[] = [];
  add(num: number) {
    this.list.push(num)
  }
  min(): number {
    var minnum = this.list[0];
    for (var i = 0; i < this.list.length; i++) {
      if (minnum > this.list[i]) {
        minnum = this.list[i];
      }
    }
    return minnum;
  }
}
var m = new MinClass();
m.add(2);
m.add(22);
m.add(1);
m.add(23);
alert(m.min())
//类的泛型 有类型校验 可以指定任意类型
class MinClass<T>{
  public list: T[] = [];
  add(value: T): void {
    this.list.push(value);
  }
  min(): T {
    var minnum = this.list[0];
    for (var i = 0; i < this.list.length; i++) {
      if (minnum > this.list[i]) {
        minnum = this.list[i];
      }
    }
    return minnum;
  }
}
var m1 = new MinClass<number>();//实例化类 并且制定了类的T代表的类型是number
m1.add(2);
m1.add(22);
m1.add(1);
m1.add(23);
alert(m1.min())

泛型接口

//函数类型接口
interface ConfigFn {
    //要求传入两个string类型参数 返回值也为string类型
  (value1: string, value2: string): string;
}
//实现
var setData: ConfigFn = function (value1: string, value2: string): string {
  return value1 + value2;
}
setData('name', 'zhangsan');

//泛型接口1
interface ConfigFn {
  <T>(value: T): T;
}
var getData: ConfigFn = function <T>(value: T): T {
  return value;
}
getData<string>('zhangsan');

//泛型接口2
interface ConfigFn<T> {
  (value: T): T;
}
function getData<T>(value: T): T {
  return value;
}
var myGetData: ConfigFn<string>=getData;
myGetData('20')//正确
//myGetData(20)//错误

把类当作参数的泛型类

1、定义个类

2、把类作为参数来约束数据传入的类型

// 定义一个User的类 这个类的作用就是映射数据库字段
// 然后定义一个MysqlDb的类 这个类用于操作数据库
// 然后把User类作为参数传入到MysqlDb中
class User {
  username: string | undefined;
  password: string | undefined;
}

class MysqlDb {
  add(user: User): boolean {
    console.log(user);
    return true;
  }
}

var u = new User();
u.username = 'zhangsan';
u.password = '123456';

var Db = new MysqlDb();
Db.add(u);
//泛型实现
class MysqlDb<T>{
  add(info: T): boolean {
    console.log(info);
    return true;
  }
}
//给user表增加数据
//1、定义一个user类和数据库进行映射
class User {
  username: string | undefined;
  password: string | undefined;
}
var u = new User();
u.username = 'zhagnsan';
u.password = '123456';
var Db = new MysqlDb<User>();
Db.add(u);


//2、定义一个Articlecate类 和数据库进行映射
class ArticleCate {
  title: string | undefined;
  desc: string | undefined;
  status: number | undefined;
  constructor(params: {
    title: string | undefined,
    desc: string | undefined,
    status?: number | undefined,
  }) {
    this.title = params.title;
    this.desc = params.desc;
    this.status = params.status;
  }
var a = new ArticleCate({
    title: '分类',
    desc:'111',
    status:1
  });
var Db=new MysqlDb<ArticleCate>();
Db.add(a);

类型 接口 类 泛型综合使用

功能:定义一个操作数据库的库 支持 Mysql Mssql MongoDb

要求1:Mysql Mssql MongoDb功能都一样 都有 add update delete get 方法

注意:约束统一的规范 以及代码重用

解决方案:需要约束规范所以要定义接口 需要代码重用所以用到泛型

  1. 接口 在面向对象编程中 接口是一种规范的定义 它定义了行为和动作的规范
  2. 泛型 通俗理解 :泛型就是解决 类 接口 方法的复用性
interface DBI<T> {
  add(info: T): boolean;
  update(info: T, id: number): boolean;
  delete(id: number): boolean;
  get(id: number): any[];
}

//定义一个操作musql数据库的类 要实现泛型接口 这个类也应该是一个泛型类
class MysqlDb<T> implements DBI<T>{
  add(info: T): boolean {
    //throw new Error("Method not implemented.");
    console.log(info);
    return true;

  }
  update(info: T, id: number): boolean {
    throw new Error("Method not implemented.");
  }
  delete(id: number): boolean {
    throw new Error("Method not implemented.");
  }
  get(id: number): any[] {
    throw new Error("Method not implemented.");
  }
}
//定义一个操作mysql数据库的类
class MssqlDb<T> implements DBI<T>{
  add(info: T): boolean {
    throw new Error("Method not implemented.");
  }
  update(info: T, id: number): boolean {
    throw new Error("Method not implemented.");
  }
  delete(id: number): boolean {
    throw new Error("Method not implemented.");
  }
  get(id: number): any[] {
    throw new Error("Method not implemented.");
  }
}
//操作用户表 定义一个user类和数据表做映射
class User {
  username: string | undefined;
  password: string | undefined;
}
var u = new User();
u.username = "张三";
u.password = "123456";
var oMysql = new MysqlDb<User>();
oMysql.add(u);

模块

模块的概念

​ 关于术语的一点说明:请务必注意一点 typescript1.5里术语已经发生了变化 内部模块现在称作命名空间

​ 外部模块现在则成为模块 模块在其自身的作用域里执行 而不是在全局作用域里

​ 这意味着定义在一个模块里的变量 函数 类等等在模块内部是不可见的 除非你使用明确的export形式之一导出他们

​ 相反 如果想使用其他模块导出的变量 函数类 接口等的时候 你必须导入他们 可以使用import形式之一

模块的概念

​ 我们可以把一些公共的功能单独抽离成一个文件作为一个模块

​ 模块里面的变量 函数 和类默认是私有的 如果我们要在外部访问模块里的数据(变量 函数 类)

​ 我们需要使用exports 暴露模块里面的数据(变量,函数 类)

​ 暴露后我们通过import引入模块就可以使用模块 里面暴露的数据(变量 函数 类……)

模块导出的几种方法

//db.ts
var dabUrl = "xxxxx";
export function getData(): any[] {
  console.log('获取数据库中的数据');
  return [{
    title: '12345'
  },
  { title: '12345' }
  ]
}
//index.ts
import {getData} from './modules/db';
getData();
//db.ts
var dabUrl = "xxxxx";
export function getData(): any[] {
  console.log('获取数据库中的数据');
  return [{
    title: '12345'
  },
  { title: '12345' }
  ]
}
function save() {
  console.log('保存数据成功');
}
export { dbUrl, getData, save }
//index.ts
import { dbUrl, getData } from './modules/db';
console.log(dbUrl);
getData();

//import { dbUrl, getData as get } from './modules/db';可以设置别名
//console.log(dbUrl);
//get();

export default 默认导出

每个模块都可以有一个默认导出 默认导出舒勇default关键字标记 并且一个模块只能有一个default导出 需要用一种特殊形式类导入

导出:export default getData

导入:import getData from ‘./modules/db’

​ getData();

命名空间

在代码量较大的情况下 为了避免各种变量命名相冲突 可将相似功能的函数 类 接口等放置到命名空间内

同java包 .net的命名空间一样 typescript的命名空间 可以将代码包裹起来 只对外暴露需要在外部访问的对象 命名空间内的对象 通过export

命名空间和模块的区别:

命名空间:内部模块 主要用于组织代码 避免命名冲突

模块 : ts外部模块的简称 侧重代码的复用 一个模块里可能有多个命名空间

namespace A {
  interface Animal {
    name: string;
    eat(str: string): void;
  }
  export class Dog implements Animal {
    name: string;
    constructor(theName: string) {
      this.name = theName;
    }
    eat() {
      console.log('${this.name} 吃粮食');
    }
  }
  class Cat implements Animal {
    name: string;
    constructor(theName: string) {
      this.name = theName;
    }
    eat() {
      console.log('${this.name} 吃狗粮');
    }
  }
}

var d = new A.Dog('狼狗');
d.eat();
    namespace B {
  interface Animal {
    name: string;
    eat(str: string): void;
  }
  export class Dog implements Animal {
    name: string;
    constructor(theName: string) {
      this.name = theName;
    }
    eat() {
      console.log('${this.name} 吃粮食');
    }
  }
  class Cat implements Animal {
    name: string;
    constructor(theName: string) {
      this.name = theName;
    }
    eat() {
      console.log('${this.name} 吃狗粮');
    }
  }
}

var c = new B.Dog('小花');
c.eat();

可以将多个命名空间放到一个模块中

//a.ts
export namespace A {
  interface Animal {
    name: string;
    eat(str: string): void;
  }
  export class Dog implements Animal {
    name: string;
    constructor(theName: string) {
      this.name = theName;
    }
    eat() {
      console.log('${this.name} 吃粮食');
    }
  }
  class Cat implements Animal {
    name: string;
    constructor(theName: string) {
      this.name = theName;
    }
    eat() {
      console.log('${this.name} 吃狗粮');
    }
  }
}

var d = new A.Dog('狼狗');
d.eat();
    export namespace B {
  interface Animal {
    name: string;
    eat(str: string): void;
  }
  export class Dog implements Animal {
    name: string;
    constructor(theName: string) {
      this.name = theName;
    }
    eat() {
      console.log('${this.name} 吃粮食');
    }
  }
  class Cat implements Animal {
    name: string;
    constructor(theName: string) {
      this.name = theName;
    }
    eat() {
      console.log('${this.name} 吃狗粮');
    }
  }
}
 //b.ts
 import {A,B} from './modules/animal';
 var d=new A.Dog('小黑');
 d.eat();
 var dog=new B.Dog('小花');
 dog.eat()

装饰器

装饰器 :装饰器是一种特殊类型的声明,它能够被附加到类声明 方法 属性或参数上 可以修改类的行为

通俗来讲装饰器就是一种方法 可以注入到类 方法属性参数上来扩展类 属性 方法 参数的功能

常见的装饰器有:类装饰器 属性装饰器 方法装饰器 参数装饰器

装饰器的写法: 普通装饰器 (无法传参) 装饰器工厂(可传参)

装饰器是过去几年中js最大的成就之一 已经是es7的标准特性之一

普通装饰器

//类装饰器:类装饰器在类声明之前被声明(紧靠着类声明)。类装饰器应用于类构造函数 可以用来监视 修改或替换类定义 传入一个参数 w
//类装饰器 普通装饰器 
function logClass(params: any) {
  console.log(params);
  //params就是当前类
  params.prototype.apiUrl = "动态扩展的属性";
  params.prototype.run = function () {
    console.log('我是一个run方法');

  }
}
@logClass
class HttpClient {
  constructor() {
  }
  getData() {
  }
}
var http: any = new HttpClient();
console.log(http.apiUrl);
http.run();

装饰器工厂

//类装饰器:装饰器工厂(可传参)
function logClass(params: string) {
  return function (target: any) {
    console.log(target);
    console.log(params);
  }
}
@logClass('hello')//将hello赋值给了params 给把httpClient这个类赋值给了target
class HttpClient{
  constructor(){

  }
  getData(){

  }
}

//类装饰器:装饰器工厂(可传参)
function logClass(params: string) {
  return function (target: any) {
    console.log(target);
    console.log(params);
    target.prototype.apiUrl = params;
  }
}
@logClass('http:www.baidu.com/api')//将hello赋值给了params 给把httpClient这个类赋值给了target
class HttpClient {
  constructor() {
  }
  getData() {
  }
}
var http = new HttpClient();
console.log(http.apiUrl);
//重载构造函数
//类装饰器表达式会在运行时当作函数被调用 类的构造函数作为其唯一的参数
//如果类装饰器返回一个值 他会使用提供的构造函数来替换类的声明


function logClass(target: any) {
  console.log(target);
  return class extends target {
    apiUrl: any = '我是修改后的数据';
    getData() {
      this.apiUrl = this.apiUrl + "----";
      console.log(this.apiUrl);
    }
  }

}

@logClass
class HttpClient {
  public apiUrl: string | undefined;
  constructor() {
    this.apiUrl = '我是构造函数中的apiurl'
  }
  getData() {
    console.log(this.apiUrl);
  }
}
var http = new HttpClient();
http.getData();

属性装饰器

//属性装饰器表达式会在运行时当作函数被调用 传入下列两个参数
//1、对于静态成员来说是类的构造函数 对于实例成员是类的原型
//2、成员的名字

//类装饰器
function logClass(params: string) {
  return function (target: any) {
    console.log(target);
    console.log(params);
  }
}


//属性装饰器
function logProperty(params: any) {
  return function (target: any, attr: any) {
    console.log(target);
    console.log(attr);
    target[attr] = params;
  }
}
@logClass('xxx')
class HttpClient {
  @logProperty('http://baidu.com')
  public url: any | undefined;
  constructor() {

  }
  getData() {
    console.log(this.url);

  }
}
var http: any = new HttpClient();
http.getData();

方法装饰器

方法装饰器

它会被应用到方法的 属性描述上 可以用来监视 修改或者替换方法定义

方法装饰器会在运行时传入下列三个参数 :

  1. 对于静态成员来说是类的构造函数 对于实例成员是类的原型对象
  2. 成员的名字
  3. 成员的属性描述符
//方法装饰器1
function get(params: any) {
  return function (target: any, methodName: any, desc: any) {
    console.log(target);
    console.log(methodName);
    console.log(desc);
    target.apiUrl = 'xxx';
    target.run = function () {
      console.log('run');

    }
  }
}
class HttpClient {
  public url: any | undefined;
  constructor() {
  }
  @get('www.baidu.com')
  getData() {
    console.log(this.url);
  }
}
var http: any = new HttpClient();
console.log(http.apiUrl);
http.run();
//方法装饰器2 修改方法
function get(params: any) {
  return function (target: any, methodName: any, desc: any) {
    console.log(target);
    console.log(methodName);
    console.log(desc.value);
    //修改装饰器的方法 把装饰器方法里面传入的所有参数改为string类型
    //1、保存当前的方法
    var oMethod = desc.value;
    desc.value = function (...args: any[]) {
      args = args.map((value) => {
        return String(value);
      })
      console.log(args);
      oMethod.apply(this, args);
    }
  }
}
class HttpClient {
  public url: any | undefined;
  constructor() {
  }
  @get('www.baidu.com')
  getData() {
    console.log('我是getdata中的方法');
  }
}
var http = new HttpClient();
http.getData(123, 'xxx')

方法参数装饰器

参数装饰器表达式在运行时当作函数来调用 可以使用参数装饰器为类的原型增加一些元素数据 传入下列三个参数

  1. 对于静态成员来说是类的构造函数 对于实例成员是类的原型对象
  2. 参数的名字
  3. 参数在函数参数列表中的索引
function logParams(params: any) {
  return function (target: any, methodName: any, patamsIndex: any) {
    console.log(params);
    console.log(target);
    console.log(methodName);
    console.log(patamsIndex);
  }
}
class HttpClient {
  public url: any | undefined;
  constructor() {

  }
  getData(@logParams('xxxxx') uuid: any) {
    console.log(uuid);
  }
}
var http = new HttpClient();
http.getData(123456);
//输出
// xxxx
// getdata ;f constructor:f
// getdata
// 0
// 123456
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值