typescript

前提:

1. 視頻鏈接:

主講老師大地

2. 文件鏈接:

itying-typescript教程

3. 官網(wǎng):

typescript
ts
angular

一乳乌、簡介

google研發(fā)巷嚣,為了面向大型復雜的項目捌木,使用javascript可以搭建
ts 是 javascript 的超集挎挖,包含 es6 和 es5
實現(xiàn)類似 java | c# 這種面向對象的編程語言

ts 是由 c# 之父 Anders Hejlsberg 發(fā)起的

建議使用 es6 語法

二尔破、使用

1. 安裝

npm|cnpm install -g typescript 或者
yarn global add typescript

安裝成功如下圖:


1.png

2. 使用

  • 創(chuàng)建文件 hello.ts
    寫入ts語法

  • ts 編譯成 es5 語法
    瀏覽器本身不支持ts語法
    命令: tsc hello.ts
    注意:每次運行都需要編譯

  • 配置自動化編譯腳本

    1. 創(chuàng)建 tsconfig.json 文件
      tsc --init 生成配置文件
    2. 快捷鍵 Ctrl+shift+B 選擇監(jiān)視模式 進行編譯
      每次有更新就會編譯

    tsc watch 是自動監(jiān)聽肄梨,下次保存文件就自動編譯
    tsc build 是編譯一次

三.語法

以下 typescript 簡寫為 ts

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

ts 中 為了 使代碼更規(guī)范,更有利于維護闻丑,增加了類型校驗
變量一旦確定為哪個數(shù)據(jù)類型漩怎,不可改變數(shù)據(jù)類型
函數(shù)返回值類型等等語法比較嚴格,不然語法會報錯

序號 類型 標識符 含義 備注 是否基本類型
1 布爾類型 boolean [true/false] let flag:boolean=false
2 數(shù)字類型 number [\d+.\d+] 未區(qū)分浮點類型和整數(shù)類型
3 字符串類型 string [char+] 單嗦嗡、雙引號包裹
4 數(shù)組類型 array [number...] 必須指定數(shù)組類型勋锤,如 let arr:number[] = [1,2,3], 第二種定義方式 let arr:Array<number> = [1,2] 泛型
5 元組類型 tuple 數(shù)組的一種,可以指定每個數(shù)組元素的類型 let arr:[string, number, boolean] = ['ts', 3.18, true]
6 枚舉類型 enum 事先考慮某個變量可能取得值 enum 枚舉名 { 標識符[=整型常數(shù)], ... } 侥祭,類似C語言,其中值默認為索引值叁执, 示例: enum Flag {success=1, error} let f:Flag=Flag.success
7 任意類型 any 可以賦值為任意類型 Object類型可以指定該類型 ×
8 null null 一個變量可以是基本數(shù)據(jù)類型,或者null或者undefined let num:number / null ×
9 undefined undefined 其他類型未初始化變量為undefined卑硫,但是引用會報錯;如果直接指定undefined沒有初始化就不會報錯 let num:number / null / undefined ×
10 空類型 void 一般用于方法沒有返回值 function run():void{} ×
11 never類型 never 從來不會出現(xiàn) let a:never a=(()=>{ throw new Error('錯誤') })() ×

2.函數(shù)

  • 函數(shù)的定義
    · 函數(shù)參數(shù)指定類型蚕断,返回值指定類型
    1. 函數(shù)聲明法
      function run(name:string, age:number):void{
    
      }
    
    1. 匿名函數(shù)法
      let fun = function(name:string, age:number):void{
    
      }
    
    · es5 實參和形參無需一樣欢伏,但是ts中必須一樣,如果不一樣需要配置可選參數(shù)亿乳,
    ? 必須配置到后面硝拧,才能夠不混淆
        let fun = function(name:string, age?:number):void{
            // age 可傳可不傳
        }
    
    · es5里面沒法設置默認參數(shù)径筏,ts和es6都可以設置默認參數(shù)
        let fun = function(name:string, age:number=20):void{
            // age 可傳可不傳,默認為 20
        }
        fun('zhangsan')
    
    · 剩余參數(shù)[實參數(shù)量>形參數(shù)量]
    ... 三點運算符(es6)的使用
        let fun = function(...result:number[]):void{
            // result 為數(shù)組類型使用
        }
        fun(1, 2, 3, 4)
    
  • 函數(shù)重載
    java 中方法的重載指的是兩個或兩個以上同名函數(shù)障陶,但它們的參數(shù)不一樣滋恬,這時會出現(xiàn)函數(shù)重載的情況
    ts 中重載指的是通過為同一個函數(shù)提供多個函數(shù)類型定義來實現(xiàn)多種功能的目的
    ts 需要兼容 es5 和 es6 重載的寫法, 與 java 有區(qū)別

    function getInfo(str: string): string
    function getInfo(str: number): number
    function getInfo(str: any): any {
        if (typeof str === 'string') {
            return '我的名字是' + str
        } else {
            return '我的年齡是' + str
        }
    }
    console.log(getInfo('張三')) // 我的名字是張三
    console.log(getInfo(20)) // 我的年齡是20
    
  • 箭頭函數(shù) es6 () => {}
    this 上下文指向函數(shù)運行的上下文抱究, 非私有

3.類(上) —— es5 中的類

  • Es5中的類和靜態(tài)方法

    // 1. 最簡單的類 - 通過構造函數(shù)
    function Person() { this.name='張三'}
    var p = new Person()
    alert(p.name)
    // 2. 構造函數(shù)和原型鏈增加屬性或者方法
    // 區(qū)別: 實例不會共享構造函數(shù)的屬性和方法恢氯, 原型鏈會
    function Person() { 
        this.name='張三'
        this.run = function () { return this.name + '在奔跑' } 
    }
    Person.prototype.work = function () { return this.name + '在工作' }
    var p = new Person()
    alert(p.run)
    alert(p.work)
    
    // 3. 類里面的靜態(tài)方法
    // 實例方法必須 new 一個實例才可以使用,靜態(tài)相當于默認就有
    Person.getInfo = function () { return '我是靜態(tài)方法' }
    alert(Person.getInfo())
    
  • Es5 繼承(原型鏈繼承昆淡、對象冒充繼承仲墨、原型鏈+對象冒充組合繼承)

    1. 對象冒充繼承
    function Person() { 
        this.name='張三'
        this.run = function () { return this.name + '在奔跑' } 
    }
    Person.prototype.work = function () { return this.name + '在工作' }
    var p = new Person()
    // Web 類 繼承 Person 類
    // 1. 對象冒充實現(xiàn)繼承
    function Web() {
        Person.call(this) // 對象冒充實現(xiàn)繼承
    }
    var w = new Web()
    console.info(w.run()) // 對象冒充可以繼承構造函數(shù)的屬性和方法
    // console.info(w.work()) // 但是無法繼承原型鏈上的屬性和方法
    
    
    1. 原型鏈繼承
    function Person(name) { 
        this.name = name
        this.run = function () { return this.name + '' } 
    }
    Person.prototype.work = function () { return this.name + '在工作' }
    var p = new Person()
    // Web 類 繼承 Person 類
    // 2. 原型鏈實現(xiàn)繼承
    function Web(name) {
    }
    Web.prototype = new Person()
    var w = new Web()
    console.info(w.run()) // 可以繼承構造函數(shù)的屬性和方法   undefined在奔跑
    console.info(w.work()) // 可以繼承原型鏈上的屬性和方法 undefined在工作
    // 問題: 實例化子類的時候蜘矢,無法給父類傳參
    
    
    1. 原型鏈+對象冒充組合繼承
    function Person(name) {
        this.name = name
        this.run = function () {
            return this.name + '在奔跑'
        }
    }
    Person.prototype.work = function () {
        return this.name + '在工作'
    }
    // 2. 原型鏈+對象冒充組合實現(xiàn)繼承
    function Web(name) {
        Person.call(this, name)
    }
    Web.prototype = new Person() // 或者 Web.prototype = Person.prototype
    var w = new Web('zhangsan')
    console.info(w.run()) // 可以繼承構造函數(shù)的屬性和方法
    console.info(w.work()) // 可以繼承原型鏈上的屬性和方法
    
    

4.類(下) —— ts 中的類

  • 類的定義
    class 關鍵字

    class Person {
        name:string;  // 屬性,前面省略了 public 關鍵字【默認】
        constructor(name:string) { // 構造函數(shù)敢靡,實例化類的時候觸發(fā)的方法
            this.name = name
        }
        run():void {
            console.info(`${this.name}在跑步`)
        }
    }
    // 調(diào)用
    let p = new Person('小張')
    p.run()
    
  • 繼承
    extends 關鍵字, super 關鍵字

    // 繼承 Person
    class worker extends Person {
        constructor(name:string){
            super(name)
        }
        // 方法先看子類是否有苦银,然后父類
    }
    let w = new Web('李四')
    console.log(w.run())
    
  • 類里面的修飾符 - public,protected,private
    public: 公有 啸胧, 全都可以訪問【默認】
    protected: 保護 , 類和子類可以訪問
    private: 私有 幔虏, 類可以訪問

2.png
  • 靜態(tài)屬性或者靜態(tài)方法 - static 關鍵字

    class Person{
        public name:string;
        static a:number = 0;
        constructor(name:string) {
            this.name = name
        }
        run ():void{
            console.log(`${this.name}在奔跑`)
        }
        static print():void{ 
            // 靜態(tài)方法無法直接調(diào)用類里的屬性 纺念, static語法類似 C 語言
            // 當前類里面的全局存在
            console.info(`靜態(tài)方法` + this.a++)
        }
    }
    Person.print()
    
    
  • 抽象類 繼承 多態(tài)

    1. 多態(tài):父類定義一個方法不去實現(xiàn),讓繼承它的子類去實現(xiàn) 所计, 每個子類根據(jù)自己的特性去定義不同的表現(xiàn)
      多態(tài)屬于繼承

      class Animal {
          name: string
          constructor(name: string) {
              this.name = name
          }
          eat() {
              console.log('吃的方法')
          }
          work() {
              console.log('工作的方法')
          }
      }
      
      class Dog extends Animal {
          constructor(name: string) {
              super(name)
          }
          eat() {  // this is 多態(tài)
              return '主人已經(jīng)準備好狗糧柠辞,快來吃飯!'
          }
      }
      
    2. 抽象方法 - abstract 關鍵字
      ts 中的抽象類主胧,是提供其他類繼承的基類/父類叭首,不能直接實例化
      abstract關鍵字來定義抽象類和抽象方法,抽象類中的抽象方法不包含具體實現(xiàn)并且必須在派生類中實現(xiàn)
      作用: 抽象類和抽象方法用于定義標準

      // 定義animal子類必須包含eat方法
      abstract class animal { // 抽象類
          // 可以包含非抽象方法
          work() {
      
          }
          abstract eat(): any; // 抽象方法踪栋, 抽象方法只能在抽象類中定義
      }
      

5.接口

interface 關鍵字

接口的作用:
在面向對象的編程中焙格,接口是一種規(guī)范的定義
它定義了行為和動作的規(guī)范,起到限制和規(guī)范的作用夷都。
接口定義了某類所需遵守的規(guī)范眷唉,不關注類的內(nèi)部狀態(tài)數(shù)據(jù),也不關注類里面方法的實現(xiàn)細節(jié)囤官,它只規(guī)定類里必須提供某些方法冬阳,提供方法的類就可以滿足實際需要。
ts 中的接口類似于 java, 同時還增加了更靈活的接口類型党饮,包括屬性肝陪、函數(shù)、可索引和類等刑顺。

  • 屬性類接口 —— 對 json 的約束
    function printLabel(labelInfo: { label: string }):void {
        // 對傳參 labelInfo 進行了規(guī)定氯窍,必須要有 string類型的 label屬性
    }
    // 對傳入對象的約束 : 屬性接口
    interface Label {
        label: string; // 必須要有 label
        fontSize?: number; // 可選參數(shù)饲常,可傳可不傳
    }
    // 規(guī)定形參
    function print(label:Label):void {
        // console.info(label.name + label.name) // 語法報錯
        // 需要嚴格遵守規(guī)則
    }
    let obj = {
        name: 1,
        label: 'hah'
    }
    print(obj) // 可以有其他屬性
    print({ label: 'jajja'  }) // 只能有 label 屬性,否則報錯
    
    
  • 函數(shù)類型接口 : 對方法傳入的參數(shù) 以及返回值進行 約束

    // 加密的函數(shù)類型接口
    interface encrypt {
        (key:string,value:string):string;
    }
    let md5: encrypt = function (k: string, v: string): string { return k + v; }
    console.log(md5('1', '2'))
    
    • 可索引接口 : 數(shù)組狼讨、對象的約束(不常用)
    // 對數(shù)組的約束
    interface UserArr {
        [index: number]: string; // 索引值為 string 類型贝淤, index 為索引
    }
    let arr: UserArr = ['aaa', 'bbb']
    console.log(arr[0]) // 0 是指 index
    
    // 對對象的約束,  可索引接口
    interface UserObj {
        [index: string]: number; // 索引值為 number 類型政供, index 為索引
    }
    let obj1:UserObj = { name: 1, k: 2 }
    console.log(obj1.name) // name 是指 index
    
    
  • 類類型接口: 對類的約束 和 抽象類有的相似
    implements 關鍵字

    // 類類型接口: 對類的約束 和 抽象類有點相似
    interface Animal2 {
        name: string;
        eat(): string;
    }
    class Dog1 implements Animal2 {
        name: string
        constructor(name: string) {  // 構造函數(shù) 初始化 name
            this.name = name
        }
        eat() {
            return `${this.name}在吃飯`
        }
    }
    let d1 = new Dog1('嘿嘿')
    console.log(d1.eat())
    
  • 接口擴展: 接口可以繼承接口
    關鍵字 interfaceextends 的合用

    // 接口擴展:接口可以繼承接口
    interface Animal3 {
        eat(): void;
    }
    interface Person1 extends Animal3 {
        work(): void;
    }
    class Programmer {
        name: string
        constructor(name: string) {
            this.name = name
        }
        coding() {
            return this.name + '在敲代碼中...'
        }
    }
    class Web implements Person1 {
        eat() {}
        work() {}
    }
    
    class Web1 extends Programmer implements Person1 {
        eat() {}
        work() {}
    }
    let web1 = new Web1('zhang')
    console.info(web1.coding())
    

6.泛型

泛型: 軟件工程中播聪,我們不僅要創(chuàng)建一致的定義良好的API,同時也要考慮可重用性鲫骗。
組件不僅能夠支持當前的數(shù)據(jù)類型犬耻,同時也能支持未來的數(shù)據(jù)類型,這在創(chuàng)建大型系統(tǒng)時
為你提供了十分靈活的功能执泰。

在 c# 或者 java 等語言中枕磁,可以使用泛型來創(chuàng)建可重用的組件,一個組件可以支持多種類型的數(shù)據(jù)术吝,方便用戶以自己的數(shù)據(jù)類型來使用組件

通俗理解: 泛型就是解決類计济、接口、方法的復用性排苍、對不特定數(shù)據(jù)類型的支持

  • 泛型函數(shù)/方法

    // 泛型: 傳入類型靈活沦寂, 函數(shù)增強復用性, 拒絕不必要的冗余代碼
    function getPerson(name: any): any { // any 類型
        return name
    }
    getPerson(111)
    // T(任意字符) 表示類型淘衙,具體由方法調(diào)用的時候決定
    function getPerson1<T>(name: T, key: string): any { // any 類型
        console.log(name)
        return name + key
    }
    getPerson1<number>(111, 'aa')
    getPerson1<string>('ahhahah', 'aaa')
    
  • 泛型類:

    // 比如有個最小堆算法传藏,需要同時支持返回數(shù)字和字符串兩種類型
    class MinClass<T>{
        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 l1 = new MinClass<string>()
    l1.add('a')
    l1.add('b')
    l1.add('c')
    console.info(l1.min())
    

    泛類:泛型可以避免重復的代碼以及對不特定的數(shù)據(jù)類型的支持(類型校驗),下面我們把類當做參數(shù)的泛型類
    其可以去除重復代碼彤守,可以對類型進行校驗

    /**
     * 1. 定義個類
     * 2. 把類作為參數(shù)來約束數(shù)據(jù)傳入的類型
     */
    /**
     * 需求:
     * 1. 定義一個 User 的類毯侦,作用是映射數(shù)據(jù)庫字段
     * 2. 定義一個 MysqlDb 的類,用于操作數(shù)據(jù)庫
     * 3. 把 User 類作為參數(shù)傳入到 MysqlDb 中
     * 
     * ` 非常像 java 中的 dto 層 `
     */
    class User {
        username: string | undefined;
        password: string | undefined;
    }
    
    // 操作數(shù)據(jù)庫的泛型類
    // 可以去除重復代碼具垫,可以對類型進行校驗
    class MysqlDb<T> {
        list:T[] = [] // 模擬數(shù)據(jù)庫
        constructor(l?: T[]) {
            if (l) {
                this.list = l
            }
        }
        add(user: T): boolean {
            this.list.push(user)
            console.log(user)
            return true
        }
    }
    var user1 = new User()
    user1.username = '張三'
    user1.password = '111'
    var mysql1 = new MysqlDb<User>()
    mysql1.add(user1)
    

    NOTES:

    1. 語法和 java 大差不差 侈离, 都是為了面向對象進行服務
    2. 這種復用性又讓我想起了原生es5,原型鏈方法
  • 泛型接口

    interface ConfigFn{
        <T>(value: T, key: string): T;
    }
    let getData: ConfigFn = function <T>(value: T, k: string): T {
        console.log(value + k)
        return value
    }
    
    getData<string>('hahha', 'hhah')
    

7. ts 中的類型筝蚕、接口卦碾、類、泛型的綜合使用案例 —— ts 封裝統(tǒng)一操作 Mysql 起宽、 Mongodb 洲胖、 Mssql 的底層庫

需求分析如下:
功能:定義一個操作數(shù)據(jù)庫的庫, 支持 Mysql Mssql Mongodb
要求1:Mysql Mssql Mongodb 功能一樣坯沪, 都有 增刪改查(add,update,delet,get)方法
注意:約束統(tǒng)一的規(guī)范绿映,以及代碼重用
解決方案:需要約束規(guī)范所以要定義接口,需要代碼重用所以用到泛型
1. 接口: 在面向對象的過程中屏箍,接口是一種規(guī)范的定義绘梦,它定義了行為和動作的規(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ù)庫的類   tip: 實現(xiàn)泛型接口 類也要是泛型類
class MySqlDb<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.");
    }
}

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.");
    }
}

class MongoDb<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 類和數(shù)據(jù)表做映射
class User {
    id: number | undefined;
    username: string | undefined;
    password: string | undefined;
    constructor(id: number, username: string, password: string) {
        this.id = id
        this.username = username
        this.password = password
    }
}
let u1 = new User(1, 'lily', '111111')
// let mMysql = new MySqlDb() // 沒有校驗作用
let mMySql = new MySqlDb<User>() // 類作為參數(shù)來約束數(shù)據(jù)傳入的類型
mMySql.add(u1) 
let mMsSql = new MsSqlDb<User>() // 類作為參數(shù)來約束數(shù)據(jù)傳入的類型
mMsSql.add(u1) 

8. ts 模塊

js 模塊化 學習
ts 模塊的概念(官方):
· ts1.5發(fā)生了一些術語的變化,‘內(nèi)部模塊’ 稱為 ‘命名空間’
· ‘外部模塊’現(xiàn)在簡稱為‘模塊’颖御,模塊在其自身的作用域里執(zhí)行榄棵,而不是在全局作用域里,說明在一個模塊里的變量潘拱、函數(shù)疹鳄、類等等在模塊外部不可見(不暴露、封裝性) 芦岂,除非 export 瘪弓, 需要使用的時候使用 import 引入 export 暴露的方法、類禽最、變量等等腺怯。

語法與 es6 相同

``` typescript
// index.ts 使用
import {User, UserModel} from './7-ts-modules/model/User'
import {Article, ArticleModel} from './7-ts-modules/model/Article'

/**
 * 案例 之 7-ts 進行模塊化
 */
var u = new User(1, 'lily', '111111')
UserModel.add(u)
var article = new Article(1, '特大新聞!特大新聞川无!今天有毛毛雨呛占!', 'lily')
ArticleModel.add(article)


// db.ts
interface DBI<T>{
    add(info: T): boolean;
    update(info: T, id: number): boolean;
    delete(id: number): boolean;
    get(id: number): any[];
}
// 定義一個操作 mysql 數(shù)據(jù)庫的類   tip: 實現(xiàn)泛型接口 類也要是泛型類
export class MySqlDb<T> implements DBI<T>{
    add(info: T): boolean {
        console.info(info)
        return true
    }
    update(info: T, id: number): boolean {
        return true
    }
    delete(id: number): boolean {
        return true
    }
    get(id: number): any[] {
        return []
    }
}

export class MsSqlDb<T> implements DBI<T>{
    add(info: T): boolean {
        console.log(info)
        return true
    }
    update(info: T, id: number): boolean {
        return true
    }
    delete(id: number): boolean {
        return true
    }
    get(id: number): any[] {
        return []
    }
}

// User.ts
import {MySqlDb} from '../db/db'

class User {
    id: number | undefined;
    username: string | undefined;
    password: string | undefined;
    constructor(id: number, username: string, password: string) {
        this.id = id
        this.username = username
        this.password = password
    }
}

let UserModel = new MySqlDb<User>() // 類作為參數(shù)來約束數(shù)據(jù)傳入的類型

export { User, UserModel }

// 同理 > Article.ts
import {MsSqlDb} from '../db/db'

class Article {
    id: number | undefined;
    title: string | undefined;
    author: string | undefined;
    constructor(id: number, title: string, author: string) {
        this.id = id
        this.title = title
        this.author = author
    }
}

let ArticleModel = new MsSqlDb<Article>() // 類作為參數(shù)來約束數(shù)據(jù)傳入的類型

export { Article, ArticleModel }

```

引入其他模塊之后,編譯之后的文件路徑會有所變化

Notes:

  1. 可以感受到 ts 不僅可以用于 網(wǎng)頁懦趋, 還可以用于 大型程序多人開發(fā)晾虑, nodejs環(huán)境...
  2. 其編程思想仍然更古不變,編程思想仅叫,設計模式很重要

9. 命名空間

定義:
代碼量較大的情況下帜篇,為了避免各種變量命名相沖突,可將相似功能的函數(shù)惑芭、類坠狡、接口等放置到命名空間內(nèi)
同 java 的包、.Net 的命名空間一樣遂跟, ts 的命名空間可以將代碼包裹起來逃沿,只對外暴露需要在外部訪問的對象。
命名空間內(nèi)的對象通過 export 暴露
與模塊的區(qū)別:

名稱 區(qū)分
命名空間 內(nèi)部模塊幻锁,主要用于組織代碼凯亮,避免命名沖突
模塊 ts 的外部模塊簡稱,側重代碼的復用哄尔,一個模塊里可能會有多個命名空間

相同點: 解決的都是代碼作用域的問題

利用 namespace 關鍵字:

``` typescript
namespace PersonA {
    interface Animal {
        name: string;
        eat() : void;
    }
    export class Dog implements Animal {
        name: string;
        constructor(name:string) {
            this.name = name
        }
        eat() {
            console.log('小狗在吃飯')
        }

        export namespace H {
            let name: string = 'jaj'
        }
    }
}

namespace PersonB {

}

let dog = new PersonA.Dog('花花')
dog.eat()
```

10. 裝飾器

定義:
裝飾器是一種特殊類型的聲明假消,它能夠被附加到類聲明、方法岭接、屬性或參數(shù)上富拗,可以修改類的行為臼予。
通俗理解: 裝飾器是一個方法,可以注入到類啃沪、方法粘拾、屬性參數(shù)來擴展他們的功能。
常見的裝飾器有: 類裝飾器创千、屬性裝飾器缰雇、方法裝飾器、參數(shù)裝飾器
裝飾器的寫法: 普通裝飾器(無法傳參)追驴、裝飾器工廠(可傳參)
裝飾器是過去幾年中 js 最大的成就之一械哟,已經(jīng)是 es7 的標準特性之一

  • 類裝飾器: 在類聲明之前被聲明(緊靠著聲明)。
    類裝飾器應用于類構造函數(shù)殿雪,可以用來監(jiān)視暇咆、修改、替換類定義丙曙,傳入一個參數(shù)
    es6 也有裝飾器 decorator{}

    1. 普通方法(無法傳參)
    function logClass(params: any) {
        console.info(params) // 當前的類
    
        params.url = 'hahha'
        params.prototype.Url = 'XXXX'
        params.prototype.run = function (): void {
            console.info('running....')
        }
    }
    
    @logClass
    class HttpClient1 {
        constructor() {
            
        }
        getData() {
    
        }
    }
    
    var http: any = new HttpClient1()
    console.log(http.url)  // 無法獲取糯崎, undefined
    console.log(http.Url)
    http.run()
    
    1. 裝飾器工廠(可傳參)
    // 2. 類裝飾器:裝飾器工廠(可傳參)
    namespace class2 {
        function logClass(params: string) {
            
            return function (target: any) {
                console.log(target)  // 當前的類
                console.info(params) // 裝飾器傳入?yún)?shù)
                target.prototype.url = params
                target.prototype.run = function (): void {
                    console.info('running....')
                }
    
            }
        }
    
        @logClass('http://xxx.com/api')
        class HttpClient1 {
            constructor() {
                
            }
            getData() {
    
            }
        }
    
        var http: any = new HttpClient1()
        console.log(http.url) 
        http.run()
    }
    
    1. 類裝飾器替換類的構造函數(shù)
    function logClass(target: any) {
        
        return class extends target () {
            // 相當于重寫,因為每個屬性都需要 extends
            constructor() {
            
            }
            getData() {
    
            }
        }
    }
    
    @logClass
    class HttpClient1 {
        constructor() {
            
        }
        getData() {
    
        }
    }
    
  • 屬性裝飾器
    都是語法糖

    function logClass (params: any){
        return function (target: any, attr: any) {
            console.log(target) // 類
            console.log(attr)  // url
            target[attr] = params
        }
    }
    
    // @logClass('http://itying.com')
    // var url: any | undefined;  // 無效
    
    class ht1 {
        @logClass('http://itying.com')
        public url: any | undefined;
    }
    var t = new ht1()
    console.log(t.url)
    
  • 方法裝飾器
    方法裝飾器在運行時傳入下列 3 個參數(shù):

    1. 對于靜態(tài)成員來說是類的構造函數(shù)河泳,對于實例成員是類的原型對象
    2. 成員的名字
    3. 成員的屬性描述符

    跟 es6 的相似

    // 方法裝飾器
    function get(params: any) {
        return function (target: any, methodName: any, desc: any) {
            // console.log(target) // 對于靜態(tài)成員來說是類的構造函數(shù)沃呢,對于實例成員是類的原型對象
            // console.log(methodName) // 成員的名字
            // console.log(desc) // 成員的屬性描述符
            
            // 修改裝飾器的方法, 把裝飾器方法里面?zhèn)魅氲乃袇?shù)改為 string 類型
            // 1. 保存當前的方法
    
            let oMethod = desc.value  // 保存當前方法
            // 修改當前方法
            desc.value = function (...args: any[]) {
                args = args.map((val) {
                    return String(val)
                }) 
                console.log('裝飾器中轉換的形參:' , args)
                oMethod.apply(this, args)  // 融合類中的 該方法語句
            }
        }
    }
    
    class Ht {
        url: string | undefined;
        constructor() {
        }
    
        @get('http://www.itying.com')
        getData(...args:any[]) {
            console.log(args)
            console.log('我是類中的方法')
        }
    }
    let ht = new Ht()
    ht.getData(12, 11, true)
    
  • 參數(shù)裝飾器
    不常用拆挥, 其他裝飾器也可以實現(xiàn)

    // 方法參數(shù)裝飾器
    function logParams(params: any) {
        return function (target: any, methodName: any, paramsIndex: any) {
            console.log(target)
            console.log(methodName)
            console.log(paramsIndex)
            target.url = params
        }
    }
    class Ht {
        url: string | undefined;
        constructor() {
        }
    
        getCan(@logParams('uuid') uuid: any) {
            console.log(uuid)
            console.log('我是類中的參數(shù)方法')
        }
    }
    let ht = new Ht()
    ht.getCan('jjj')
    console.log(ht.url)
    

裝飾器順序:

順序 名稱 多個內(nèi)部順序
1 屬性裝飾器
2 方法裝飾器
3 方法參數(shù)裝飾器 先執(zhí)行后面的薄霜,從后向前
4 類裝飾器 先執(zhí)行后面的,從后向前

四.案例 【 ts + angular 】

前提:

安裝angular/cli:
npm|cnpm install -g @angular/cli
驗證:
ng version
新建項目:
ng new demo01

scss 和 sass 的區(qū)別:scss是sass的一個升級版本纸兔,完全兼容sass之前的功能惰瓜,又有了些新增能力

  1. 文件擴展名不同,sass是以“.sass”后綴為擴展名汉矿,而SCSS是以“.scss”后綴為擴展名崎坊。
  2. 語法不同,sass是以嚴格的縮進式語法規(guī)則來書寫洲拇,而scss的語法與css語法非常相似奈揍。

運行項目:
ng serve --open

來自b站視頻觀看筆記,有錯請指正8承男翰!

?著作權歸作者所有,轉載或內(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級特大地震影響躺枕,放射性物質(zhì)發(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)容