TypeScript 基礎入門及綜合案例使用

TypeScript

  • VS code 自動編譯 TS 文件
    1. 第一步 tsc --init生成 tsconfig.json"outdir": "./js"
    2. 第二步 任務 - 運行任務 監(jiān)視 tsconfig.json

數(shù)據(jù)類型

  • TS 中為了使編寫的代碼更加規(guī)范凹联,更有利于維護,增加了類型校驗嚣艇,在 TS 中主要提供了以下數(shù)據(jù)類型

    • 布爾類型 boolean
    • 數(shù)字類型 number
    • 字符串類型 string
    • 數(shù)組類型 array
    • 元組類型 tuple
    • 枚舉類型 enum
    • 任意類型 any
    • null 和 undefined
    • void 類型
    • nerve 類型
  • 數(shù)組類型

    • let arr: number[] = [1, 2, 3]
    • let arr: Array<number> = [1, 2, 3]
  • 元組類型

    • let arr: [number, string] = [1, "hello"]
  • 枚舉類型(enum)

    隨著計算機的不斷普及棋凳,程序不僅只用于數(shù)值計算诫咱,還更廣泛地用于處理非數(shù)值的數(shù)據(jù)莫辨。
    例如性別抒寂、年齡结啼、月份、顏色等屈芜,都不是數(shù)值數(shù)據(jù)郊愧。
    在其它程序中用自然語言中有相應含義的單詞來代表某一狀態(tài),則程序就很容易閱讀和理解井佑。
    也就是說属铁,實現(xiàn)考慮到某一變量可能取的值,盡量用自然語言中含義清楚的單詞來表示它的每一個值躬翁。
    這種方法成為枚舉方法焦蘑,用這種方法定義的類型稱枚舉類型。
    - 定義枚舉類型的方法
    ts enum 枚舉名 { 標識符[=整型常數(shù)], 標識符[=整型常數(shù)], ... 標識符[=整型常數(shù)], }
    - 使用的方法
    ```ts
    enum Color {
    blue,
    red = 30,
    'orange'
    };

          let a: Color = Color.blue
          console.log(a)  // 0
          let b: Color = Color.red
          console.log(b)  // 30
          let c: Color = Color.orange
          console.log(c)  // 31
      ```
    
  • 任意類型

    • 用法
          let oBox: any = document.getElementById('box');
          oBox.style.color = 'red';
          // oBox 不指定類型或者指定 Object 類型都會報錯盒发,所以需要指定 any 類型例嘱。
      
  • null 和 undefined

    • 用法
          let num1: undefined;
          console.log(num1);
          let num2: number | undefined
          num2 = 123
          console.log(num2)
      
  • void 類型

    • 用法
      ts function run(): void { console.log("ok") } //表示 run 函數(shù)沒有返回值
  • Never 類型

    • Never 類型是那些總是會拋出異常或根本就不會有返回值的函數(shù)表達式或箭頭函數(shù)表達式的返回值類型
    • 是其他類型(包括 null 和 undefined)的子類型宁舰,代表從不會出現(xiàn)的值
    • 這意味著聲明 never 的變量只能被 never 類型所賦值拼卵。
    • 用法:
          // 返回never的函數(shù)必須存在無法達到的終點
          function error(message: string): never {
                  throw new Error(message);
          }
      
          // 推斷的返回值類型為never
          function fail() {
                  return error("Something failed");
          }
      
          // 返回never的函數(shù)必須存在無法達到的終點
          function infiniteLoop(): never {
                  while (true) {
                  }
          }
      

函數(shù)

  • TS 中函數(shù)的定義
    • 函數(shù)聲明式
          function run(): string {
              return 'abc'
          }
      
    • 匿名函數(shù)
  • 方法可選參數(shù)
    • ES5 里面方法的實參和形參可以不一樣,但是 TS 中必須一樣蛮艰,如果不一樣就需要配置可選參數(shù)腋腮。
    • 注意:可選參數(shù)必須配置到參數(shù)的最后面。
          function getInfo(name: string, age?: number) {
              if(age) {
                  return `${name} --- ${age}`
              } else {
                  return `${name} --- 年齡保密`
              }
          }
          alert(getInfo("張三"))
      
  • 默認參數(shù)
    • ES5 中無法設置默認參數(shù),ES6 和 TS 中都可以設置默認參數(shù)
          function getInfo(name: string, age: number = 20) {
              if(age) {
                  return `${name} --- ${age}`
              } else {
                  return `${name} --- 年齡保密`
              }
          }
          alert(getInfo("張三"))
      
  • 剩余參數(shù)
    • 利用 三點運算符 獲取剩余參數(shù)
          function sum(...result: number[]): number {
              let sum = 0
              result.forEach(item => {
                  sum += item
              })
              return sum
          }
          alert(sum(1, 2, 3, 4))
      
  • TS函數(shù)重載
    • Java 中方法的重載即寡,重載指的是兩個或者兩個以上同名的函數(shù)徊哑,但是他們的參數(shù)不一樣,這時會出現(xiàn)函數(shù)重載的情況聪富。
    • TypeScript 中的重載实柠,通過為同一個函數(shù)提供多個函數(shù)類型定義來實現(xiàn)多種功能的目的
          function getInfo(name: string): string;
          function getInfo(age: number): number;
          function getInfo(str: any): any {
              if(typeof str === 'string') {
                  return '我叫:' + str;
              } else {
                  return '我的年齡是:' + str
              }
          }
      
  • 箭頭函數(shù)

ES5 創(chuàng)建對象和繼承

  • 原型鏈 + 對象冒充的組合繼承模式
    • 繼承構造函數(shù)及其原型鏈里面的屬性和方法
          function Person(name, age) {
              this.name = name;
              this.age = age;
              this.run = function () {
                  alert(this.name + "在運動")
              }
          }
          Person.prototype.sex = "男"
          Person.prototype.work = function() {
              alert(this.name + "在工作")
          }
      
          function Web(name, age) {
              // 對象冒充實現(xiàn)繼承構造函數(shù)的屬性和方法
              Person.call(this, name, age)
          }
      
          // 實現(xiàn)繼承其原型鏈上的屬性和方法  - 下面兩種方式都可以實現(xiàn)
          // Web.prototype = new Person()
          Web.prototype = Person.prototype
      
          var w = new Web("張三");
          w.run()
          w.work()
      

TS 中的類

  • TS 中類的定義
       class Person {
           name: string;
           constructor(name: string) {
               this.name = name
           }
           run():void {
               alert(this.name)
           }
       }
    
  • TS 中實現(xiàn)繼承 - extends、super
      class Person {
          name: string;
          constructor(name: string) {
              this.name = name
          }
          run():void {
              alert(`${this.name}在運動`)
          }
      }
      class Web extends Person {
          constructor(name: string) {
              // 初始化父類的構造函數(shù)
              super(name)
          }
          work() {
              alert(`${this.name}在工作`)
          }
      }
    
  • 類里面的修飾符
    • TS 里面定義屬性的時候給我們提供了三種修飾符
      • public:共有 在類里面善涨、子類窒盐、類外面都可以訪問
      • protected:保護類型 在類里面、子類里面可以訪問钢拧,在類外面無法訪問
      • private:私有 在類里面可以訪問蟹漓,子類、類外部都無法訪問

靜態(tài)屬性源内、靜態(tài)方法

  • static 關鍵字聲明屬性或者方法
        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}在工作`)
            }
            // 靜態(tài)方法 里面無法直接調(diào)用類里面的屬性
            static print() {
                // alert("print方法" + this.age)
                alert("print方法" + Person.sex)
            }
        }
        Person.print()
    

多態(tài)

  • 父類定義一個方法不去實現(xiàn)葡粒,讓繼承它的子類去實現(xiàn),每一個子類有不同的表現(xiàn)
  • 多態(tài)也是繼承的一種表現(xiàn)膜钓,多態(tài)屬于繼承
        class Animal {
            name: string;
            constructor(name: string) {
                this.name = name
            }
            eat() { // 具體吃什么嗽交,不知道,繼承它的子類去實現(xiàn)颂斜,每一個子類的表現(xiàn)不一樣
                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 中的抽象類:它是提供其他類繼承的基類夫壁,不能直接被實例化
  • abstract 關鍵字定義抽象類和抽象方法,抽象類中的抽象方法不包含具體實現(xiàn)并且必須在派生類中實現(xiàn)
  • abstract 抽象方法只能放在抽象類里面
  • 抽象類和抽象方法用來定義標準 -- Animal 這個類要求它的子類必須包含 eat 方法
        abstract class Animal {
            public name: string;
            constructor(name: string) {
                this.name = name
            }
            abstract eat(): any;    // 抽象方法不包含具體實現(xiàn)并且必須在派生類中實現(xiàn)
        }
        class Dog extends Animal {
            constructor(name: string) {
                super(name)
            }
            // 抽象類的子類必須實現(xiàn)抽象類里面的抽象方法
            eat() {
                return this.name + '吃糧食'
            }
        }
        class Cat extends Animal {
            constructor(name: string) {
                super(name)
            }
            // 抽象類的子類必須實現(xiàn)抽象類里面的抽象方法
            // 不包含 eat 抽象方法沃疮,所以報錯了
            // 非抽象類“Cat”不會實現(xiàn)繼承自“Animal”類的抽象成員“eat”盒让。
        }
    
        // let a = new Animal()     // 不能這樣用
    
        let dog = new Dog("大黃")
        alert(dog.eat())
    

接口

接口的作用:在面向對象的編程中,接口是一種規(guī)范的定義司蔬,它定義了行為和動作的規(guī)范邑茄,在程序設計里,接口起到一種限制和規(guī)范的作用俊啼。接口定義了某一批類所需要遵守的規(guī)范肺缕,接口不關心這些類的內(nèi)部狀態(tài)數(shù)據(jù),也不關心這些類里的方法的實現(xiàn)細節(jié)授帕,它之規(guī)定這批類里必須提供某些方法同木,提供這些方法的類就可以滿足實際需要。Typescript 中的接口類似于 Java豪墅,同事還增加了更加靈活的接口類型泉手,包括屬性、函數(shù)偶器、可索引和類等。

  • 屬性接口
    • TS 中定義方法傳入?yún)?shù)
          function printLabel(label: string): void {}
          printLabel("哈哈")
      
    • TS 中定義方法傳入?yún)?shù)對 json 進行約束
          function printLabel(labelInfo: {label: string}): void {}
          printLabel("哈哈")    // 錯誤寫法
          printLabel({label: "哈哈"})       // 正確寫法
      
    • 對批量方法傳入?yún)?shù)進行約束
    • 接口:行為和動作的規(guī)范,對批量方法進行約束
          interface FullName {
              firstName: string;
              secondName: string;
          }
          function printName(name: FullName) {
              // 必須傳入對象 firstName 和 secondName
              console.log(name.firstName + '---' + name.secondName)
          }
      
  • 可選屬性
        interface FullName {
            firstName: string;
            secondName?: string;    
        }
    
  • 函數(shù)類型接口:對方法傳入的參數(shù)以及返回值進行約束
    • 加密的函數(shù)類型接口
          interface encrypt {
              (key: string, value: string): string
          }
          let run: encrypt = function(key: string, value: string): string {
              return key + value
          }
      
    • 可索引接口:數(shù)組屏轰、對象的約束 (不常用)
    • 可索引接口對數(shù)組的約束
          interface UserArr {
              [index: number]: string;
          }
          let arr: UserArr = ['123', 'bbb']
          console.log(arr[0])
      
    • 可索引接口對對象的約束
          interface UserObj {
              [index: string]: string;
          }
          let obj: UserObj = {name: '張三'}
          console.log(obj.name)
      
  1. 類類型接口:對類的約束 和 抽象類有點類似
          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 + '吃肉')
              }
          }
    
  2. 接口擴展:接口可以繼承接口
          interface Animal {
              eat(): void;
          }
          interface Person extends Animal {
              work(): void;
          }
      
          class Programmer {
              public name: string;
              constructor(name: string) {
                  this.name = name
              }
              coding(code: string) {
                  console.log(this.name + code)
              }
          }
      
          class Web extends Programmer implements Person {
              constructor(name: string) {
                  super(name)
                  this.name = name
              }
              eat() {
                  console.log(this.name + '吃饅頭')
              }
              work() {
                  console.log(this.name + '寫代碼')
              }
          }
      
          let w = new Web("小黑")
          w.eat()
          w.work()
          w.coding("寫 TS 代碼")
    

泛型

泛型:軟件工程中颊郎,我們不僅要創(chuàng)建一直的定義良好的 API,同時也要考慮可重用性霎苗。組件不僅能夠支持當前的數(shù)據(jù)類型姆吭,同事也能支持未來的數(shù)據(jù)類型,著在創(chuàng)建大型系統(tǒng)時為你提供十分靈活的功能唁盏。
在像 C# 和 Java 這樣的語言中内狸,可以使用泛型來創(chuàng)建可重用的組件,一個組件可以支持多種類型的數(shù)據(jù)厘擂。這樣用戶就可以以自己的數(shù)據(jù)類型來使用組件昆淡。
通俗理解:泛型就是解決類 接口 方法的復用性、以及對不特定類型的支持刽严。

泛型的定義

  • T 表示泛型昂灵,具體什么類型是調(diào)用這個方法的時候決定的

泛型函數(shù)

    function getData<T>(value: T):T {
        return value
    }
    getData<number>(123)

泛型類:

    class MinClass<T> {
        public list: T[] = []
        add(value: T):void {
            this.list.push(value)
        }
        min():T {
            let minNum = this.list[0];
            for(let i = 0; i < this.list.length; i++) {
                if (minNum > this.list[i]) {
                    minNum = this.list[i]
                }
            }
            return minNum
        }
    }
    let m1 = new MinClass<number>();
    m1.add(1) 
    m1.add(14) 
    m1.add(5) 
    alert(m1.min())

泛型接口

  • 基本使用
        interface ConfigFn<T> {
            (value: T): T
        }
        function getData<T>(value: T):T {
            return value
        }
        var myGetData:ConfigFn<string> = getData;
        myGetData('20')
        // myGetData(20)        // 錯誤
        // getData<string>('1234')      // 錯誤·ts
    
  • 數(shù)據(jù)庫操作
        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
            }
        }
        class MysqlDb<T> {
            add(info: T):boolean {
                console.log(info)
                return true
            }
            updated(id: number, info: T): boolean {
                console.log(info)
                return true
            }
        }
        // 添加操作
        let a = new ArticleCate({
            title: "分類",
            desc: '123',
        })
        let db = new MysqlDb<ArticleCate>()
        db.add(a)
        // 修改操作
        let b = new ArticleCate({
            title: "分類2",
            desc: '456',
            status: 1,
        })
        db.updated(123, b)
    

綜合使用

功能:定義一個操作數(shù)據(jù)庫的庫,支持 Mysql舞萄、Mssql眨补、MongDB
要求1:Mysql、Mssql倒脓、MongDB 功能一樣撑螺,都有 add、update崎弃、delete实蓬、get 方法
注意:約束統(tǒng)一的規(guī)范,以及代碼重用
解決方案:需要約束規(guī)范所以要定義接口吊履,需要代碼重用所以用到泛型
1安皱、接口:在面向對象的編程中,接口是一種規(guī)范
2艇炎、泛型 通俗理解:泛型就是解決類 接口 方法的復用性

    interface DBI<T> {
        add(info: T): boolean;
        update(info: T, id: number): boolean;
        delete(id: number): boolean;
        get(id: number): any[];
    }
    // 定義一個操作 mysql 數(shù)據(jù)庫的類       注意:要實現(xiàn)泛型接口酌伊,這個類也應該是一個泛型
    class MysqlDb<T> implements DBI<T> {
        constructor() {
            console.log("數(shù)據(jù)庫建立連接")
        }
        add(info: T): boolean {
            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[] {
            let list = [
                {
                    title: 'xxxx',
                    desc: 'xxxxx',
                },
                {
                    title: 'xxxx',
                    desc: 'xxxxx',
                },
            ]
            return list
        }
    }
    // 定義已個操作 mssql 數(shù)據(jù)庫的類
    class MssqlDb<T> implements DBI<T> {
        add(info: T): boolean {
            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.");
        }
    }
    // 操作用戶表        定義一個 User 類和數(shù)據(jù)表做映射
    class User {
        username: string | undefined;
        password: string | undefined;
    }
    let u = new User()
    u.username = "張三"
    u.password = "123456"
    let oMysql = new MysqlDb<User>()
    oMysql.add(u)
    
    let oMssql = new MssqlDb<User>();
    oMssql.add(u)
    
    // 獲取 User 表 id 為4的數(shù)據(jù)
    let data = oMysql.get(4)
    console.log(data)

模塊

模塊的概念

  • 官方:
    • 關于術語的一點說明:請務必注意一點,Typescript 1.5里面語名已經(jīng)發(fā)生變化缀踪。"內(nèi)部模塊"現(xiàn)在稱作"命名空間"
    • "外部模塊"現(xiàn)在則簡稱為"模塊"居砖,模塊在其自身的作用域里執(zhí)行,而不是在全局作用域里
    • 這意味著定義在一個模塊里的變量驴娃、函數(shù)奏候、類等等在模塊外部都是不可見的,除非你明確地使用 export 形式之一導出它們唇敞。
    • 相反蔗草,如果想使用其他模塊導出的變量咒彤、函數(shù)、類咒精、接口等的時候镶柱,你必須要導入它們,可以使用 import 形式之一模叙。
  • 理解:
    • 我們可以把一些公共的功能單獨抽離成一個文件作為一個模塊
    • 模塊里的變量歇拆、函數(shù)、類等默認是私有的范咨,如果我們要在外部訪問模塊里面的數(shù)據(jù)(變量故觅、函數(shù)、類)渠啊,
    • 我們需要通過 export 暴露模塊里面的數(shù)據(jù)(變量输吏、函數(shù)、類)
    • 暴露后我們通過 import 引入模塊就可以使用模塊里面暴露的數(shù)據(jù)(變量昭抒、函數(shù)评也、類)

命名空間

  • 在代碼量較大的情況下,為了避免各種變量命名相沖突灭返,可將相似功能的函數(shù)盗迟、類、接口等放置到命名空間內(nèi)
  • 同 Java 的包熙含、.net 的命名空間一樣罚缕,TypeScript 的命名空間可以將代碼包裹起來,只對外暴露需要外部訪問的對象怎静,命名空間內(nèi)的對象通過 export 暴露出去

命名空間和模塊的區(qū)別

  • 命名空間:內(nèi)部模塊邮弹,主要用于組織代碼,避免命名沖突
  • 模塊:ts的外部模塊的簡稱蚓聘,側重代碼的重用腌乡,一個模塊里可能會有多個命名空間
          namespace A {
              interface Animal {  }
              export class Cat { 
                  eat() {}
              }
          }
          let a = new A.Cat()
    

裝飾器

  • 裝飾器:裝飾器是一種特殊類型的聲明,它能夠被附加到類聲明夜牡、方法与纽、屬性或參數(shù)上,可以修改類的行為塘装。
  • 通俗的講急迂,裝飾器就是一個方法,可以注入到類蹦肴、方法僚碎、屬性參數(shù)上來擴展類、屬性阴幌、方法勺阐、參數(shù)的功能
  • 常見的裝飾器有:類裝飾器卷中、屬性裝飾器、方法裝飾器皆看、參數(shù)裝飾器
  • 裝飾器的寫法:普通裝飾器(無法傳參)仓坞,裝飾器工廠(可傳參)
  • 裝飾器是過去幾年中 Js 最大的成就之一背零,已是 ES7 的標準特性之一

類裝飾器

類裝飾器在類聲明之前被聲明(緊靠著類聲明)腰吟。類裝飾器應用于類構造函數(shù),可以用來監(jiān)視徙瓶,修改或替換類定義毛雇。傳入一個參數(shù)

  • 普通裝飾器(無法傳參)
          function logClass(params: any) {
              console.log(params)
              // params 就是當前類
              params.prototype.apiUrl = 'xxx'
              params.prototype.run = function() {
                  console.log("我是一個 run 方法")
              }
          }
          @logClass
          class HttpClient {
              constructor() {}
              getData() {}
          }
          let http = new HttpClient()
          console.log(http.apiUrl)
          http.run()
    
  • 裝飾器工廠(可傳參)
          function logClass(params: string) {
              return function(target: any) {
                  console.log(target)
                  console.log(params)
      
                  target.prototype.apiUrl = params
              }
          }
          @logClass('hello')
          class HttpClient {
              constructor() {}
              getData() {}
          }
          let http = new HttpClient()
          console.log(http.apiUrl)
    
  • 類裝飾器:下面是一個重載構造函數(shù)的例子
    • 類裝飾器表達式會在運行時當作函數(shù)被調(diào)用,類的構造函數(shù)作為其唯一的參數(shù)
    • 如果類裝飾器返回一個值侦镇,它會使用提供的構造函數(shù)來替換類的聲明
          function logClass(target: any) {
              console.log(target)
      
              return class extends target {
                  apiUrl: any = '我是修改后的數(shù)據(jù)'
                  getData() {
                      this.apiUrl = this.apiUrl + '----'
                      console.log(this.apiUrl)
                  }
              }
          }
      
          @logClass
          class HttpClient {
              public apiUrl: string | undefined;
              constructor() {
                  this.apiUrl = "我是構造函數(shù)中的 apiUrl"
              }
              getData() {
                  console.log(this.apiUrl);
              }
          }
          let http = new HttpClient() 
          http.getData()
      
  • 屬性裝飾器
    • 屬性裝飾器表達式會在運行時當作函數(shù)被調(diào)用灵疮,傳入下列兩個參數(shù):
      • 對于靜態(tài)成員來說是類的構造函數(shù),對于實例成員是類的原型對象
      • 成員的名字
            // 類裝飾器
            function logClass(params: string) {
                return function(target: any) {
                    // console.log(params)
                    // console.log(target)
                }
            }
        
            // 屬性裝飾器
            function logProperty(params: any) {
                return function(target: any, attr: any) {
                    console.log(params)
                    console.log(target)
                    console.log(attr)
                    target[attr] = params
                }
            }
            @logClass('xxx')
            class HttpClient {
                @logProperty('http://itying.com')
                public url: any | undefined;
                constructor() {
                    
                }
                getData() {
                    console.log(this.url)
                }
            }
            let http = new HttpClient() 
            http.getData()
        
  • 方法裝飾器
    • 它會被應用到方法的屬性描述符上壳繁,用來監(jiān)視震捣,修改或者替換方法定義。
    • 方法裝飾器會在運行時傳入下列3個參數(shù):
      • 對于靜態(tài)成員來說是類的構造函數(shù)闹炉,對于實例成員是類的原型對象
      • 成員的名字
      • 成員的屬性描述符
    • 方法裝飾器的使用
      • 方法裝飾器一
            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('http://itying.com')
                getData() {
                    console.log(this.url)
                }
            }
            let http = new HttpClient() 
            console.log(http.url)
            http.run()
        
      • 方法裝飾器二
            function get(params: any) {
                return function(target: any,methodName: any, desc: any) {
                    console.log(target)
                    console.log(methodName)
                    console.log(desc.value)
                    // 修改裝飾器的方法   把裝飾器方法里面?zhèn)魅氲乃袇?shù)改為 string 類型
                    // 1. 保存當前方法
                    let 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('http://itying.com')
                getData(...args:any[]) {
                    console.log(args)
                    console.log('getData里面的代碼')
                }
            }
            let http = new HttpClient()
            http.getData(123, '12333')
            ```
        
  • 方法參數(shù)裝飾器
    • 參數(shù)裝飾器表達式會在運行時當作函數(shù)被調(diào)用蒿赢,可以使用參數(shù)裝飾器為類的原型增加一些元素數(shù)據(jù),傳入下列3個參數(shù):
      • 對于靜態(tài)成員來說是類的構造函數(shù)渣触,對于實例成員是類的原型對象
      • 方法的名稱名字
      • 參數(shù)在函數(shù)參數(shù)列表中的索引
            function logParams(params: any) {
                return function(target: any, methodName: any, paramsIndex: any) {
                    console.log(params)
                    console.log(target)
                    console.log(methodName)
                    console.log(paramsIndex)
                    target.apiUrl = params
                }
            }
            class HttpClient {
                public url: any | undefined;
                constructor() {}
                getData(@logParams('uuid') uuid: any) {
                    console.log(uuid)
                }
            }
            let http = new HttpClient()
            http.getData(123)
            console.log(http.apiUrl)
            ```
        
    • 裝飾器執(zhí)行順序
      • 屬性 > 方法 > 方法參數(shù) > 類
      • 如果有多個同樣的修飾器羡棵,它會先執(zhí)行后面的
            function logClass1(params: string) {
                return function(target: any) {
                    console.log("類裝飾器1")
                }
            }
            function logClass2(params: string) {
                return function(target: any) {
                    console.log("類裝飾器2")
                }
            }
            function logAttribute(params?: string) {
                return function(target: any, attrName: any) {
                    console.log("屬性裝飾器")
                }
            }
            function logMethod(params?: string) {
                return function(target: any, attrName: any, desc: any) {
                    console.log("方法裝飾器")
                }
            }
            function logParams1(params?: string) {
                return function(target: any, attrName: any, desc: any) {
                    console.log("方法參數(shù)裝飾器1")
                }
            }
            function logParams2(params?: string) {
                return function(target: any, attrName: any, desc: any) {
                    console.log("方法參數(shù)裝飾器2")
                }
            }
            @logClass1("http://www.itying.com/api")
            @logClass2("xxxx")
            class HttpClient {
                @logAttribute()
                public apiUrl: string | undefined
                constructor() {
                }
                
                @logMethod()
                getData() {
                    return true
                }
                setData(@logParams1() attr1:any, @logParams2() attr2:any) {}
            }
            let http = new HttpClient()
            // 輸出順序:屬性裝飾器 方法裝飾器 方法參數(shù)裝飾器2 方法參數(shù)裝飾器2 類裝飾器2 類裝飾器1 
        
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市嗅钻,隨后出現(xiàn)的幾起案子皂冰,更是在濱河造成了極大的恐慌,老刑警劉巖养篓,帶你破解...
    沈念sama閱讀 221,695評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件秃流,死亡現(xiàn)場離奇詭異,居然都是意外死亡柳弄,警方通過查閱死者的電腦和手機舶胀,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,569評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來语御,“玉大人峻贮,你說我怎么就攤上這事∮Υ常” “怎么了纤控?”我有些...
    開封第一講書人閱讀 168,130評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長碉纺。 經(jīng)常有香客問我船万,道長刻撒,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,648評論 1 297
  • 正文 為了忘掉前任耿导,我火速辦了婚禮声怔,結果婚禮上,老公的妹妹穿的比我還像新娘舱呻。我一直安慰自己醋火,他們只是感情好,可當我...
    茶點故事閱讀 68,655評論 6 397
  • 文/花漫 我一把揭開白布箱吕。 她就那樣靜靜地躺著芥驳,像睡著了一般。 火紅的嫁衣襯著肌膚如雪茬高。 梳的紋絲不亂的頭發(fā)上兆旬,一...
    開封第一講書人閱讀 52,268評論 1 309
  • 那天,我揣著相機與錄音怎栽,去河邊找鬼丽猬。 笑死,一個胖子當著我的面吹牛熏瞄,可吹牛的內(nèi)容都是我干的脚祟。 我是一名探鬼主播,決...
    沈念sama閱讀 40,835評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼巴刻,長吁一口氣:“原來是場噩夢啊……” “哼愚铡!你這毒婦竟也來了?” 一聲冷哼從身側響起胡陪,我...
    開封第一講書人閱讀 39,740評論 0 276
  • 序言:老撾萬榮一對情侶失蹤沥寥,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后柠座,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體邑雅,經(jīng)...
    沈念sama閱讀 46,286評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,375評論 3 340
  • 正文 我和宋清朗相戀三年妈经,在試婚紗的時候發(fā)現(xiàn)自己被綠了淮野。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,505評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡吹泡,死狀恐怖骤星,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情爆哑,我是刑警寧澤洞难,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站揭朝,受9級特大地震影響队贱,放射性物質發(fā)生泄漏色冀。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,873評論 3 333
  • 文/蒙蒙 一柱嫌、第九天 我趴在偏房一處隱蔽的房頂上張望锋恬。 院中可真熱鬧,春花似錦编丘、人聲如沸与学。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,357評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽癣防。三九已至蜗巧,卻和暖如春掌眠,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背幕屹。 一陣腳步聲響...
    開封第一講書人閱讀 33,466評論 1 272
  • 我被黑心中介騙來泰國打工蓝丙, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人望拖。 一個月前我還...
    沈念sama閱讀 48,921評論 3 376
  • 正文 我出身青樓渺尘,卻偏偏與公主長得像,于是被迫代替她去往敵國和親说敏。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,515評論 2 359

推薦閱讀更多精彩內(nèi)容

  • 慕課網(wǎng)@JoJozhai 老師 TypeScript入門課程分享 TypeScript入門 ES5,ES6,JS,...
    shangpudxd閱讀 10,440評論 0 22
  • TypeScript簡介: 微軟開發(fā) javascript的超集 遵循ES6腳本語言的規(guī)范 添加了遵循ES6的語...
    咖啡浮點閱讀 841評論 0 3
  • 前言 現(xiàn)在TypeScript越來越火,咱也趕一下潮流秸弛,開始學習一下TypeScript构舟,在學習的同時做筆記記錄,...
    郝晨光閱讀 1,461評論 0 7
  • 個人看視頻整理出來的筆記架诞,如果對你沒有幫助拟淮,請關掉頁面 js和ts的區(qū)別:js實現(xiàn)了ES5 規(guī)范;ts實現(xiàn)了ES6...
    沒心x閱讀 129評論 0 1
  • Lua 5.1 參考手冊 by Roberto Ierusalimschy, Luiz Henrique de F...
    蘇黎九歌閱讀 13,835評論 0 38