typescript

前提:

1. 視頻鏈接:

主講老師大地

2. 文件鏈接:

itying-typescript教程

3. 官網(wǎng):

typescript
ts
angular

一、簡(jiǎn)介

google研發(fā),為了面向大型復(fù)雜的項(xiàng)目,使用javascript可以搭建
ts 是 javascript 的超集,包含 es6 和 es5
實(shí)現(xiàn)類似 java | c# 這種面向?qū)ο蟮木幊陶Z言

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
    注意:每次運(yùn)行都需要編譯

  • 配置自動(dòng)化編譯腳本

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

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

三.語法

以下 typescript 簡(jiǎn)寫為 ts

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

ts 中 為了 使代碼更規(guī)范,更有利于維護(hù),增加了類型校驗(yàn)
變量一旦確定為哪個(gè)數(shù)據(jù)類型,不可改變數(shù)據(jù)類型
函數(shù)返回值類型等等語法比較嚴(yán)格,不然語法會(huì)報(bào)錯(cuò)

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

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 實(shí)參和形參無需一樣,但是ts中必須一樣,如果不一樣需要配置可選參數(shù),
    ? 必須配置到后面,才能夠不混淆
        let fun = function(name:string, age?:number):void{
            // age 可傳可不傳
        }
    
    · es5里面沒法設(shè)置默認(rèn)參數(shù),ts和es6都可以設(shè)置默認(rèn)參數(shù)
        let fun = function(name:string, age:number=20):void{
            // age 可傳可不傳,默認(rèn)為 20
        }
        fun('zhangsan')
    
    · 剩余參數(shù)[實(shí)參數(shù)量>形參數(shù)量]
    ... 三點(diǎn)運(yùn)算符(es6)的使用
        let fun = function(...result:number[]):void{
            // result 為數(shù)組類型使用
        }
        fun(1, 2, 3, 4)
    
  • 函數(shù)重載
    java 中方法的重載指的是兩個(gè)或兩個(gè)以上同名函數(shù),但它們的參數(shù)不一樣,這時(shí)會(huì)出現(xiàn)函數(shù)重載的情況
    ts 中重載指的是通過為同一個(gè)函數(shù)提供多個(gè)函數(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ù)運(yùn)行的上下文, 非私有

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

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

    // 1. 最簡(jiǎn)單的類 - 通過構(gòu)造函數(shù)
    function Person() { this.name='張三'}
    var p = new Person()
    alert(p.name)
    // 2. 構(gòu)造函數(shù)和原型鏈增加屬性或者方法
    // 區(qū)別: 實(shí)例不會(huì)共享構(gòu)造函數(shù)的屬性和方法, 原型鏈會(huì)
    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)方法
    // 實(shí)例方法必須 new 一個(gè)實(shí)例才可以使用,靜態(tài)相當(dāng)于默認(rèn)就有
    Person.getInfo = function () { return '我是靜態(tài)方法' }
    alert(Person.getInfo())
    
  • Es5 繼承(原型鏈繼承、對(duì)象冒充繼承、原型鏈+對(duì)象冒充組合繼承)

    1. 對(duì)象冒充繼承
    function Person() { 
        this.name='張三'
        this.run = function () { return this.name + '在奔跑' } 
    }
    Person.prototype.work = function () { return this.name + '在工作' }
    var p = new Person()
    // Web 類 繼承 Person 類
    // 1. 對(duì)象冒充實(shí)現(xiàn)繼承
    function Web() {
        Person.call(this) // 對(duì)象冒充實(shí)現(xiàn)繼承
    }
    var w = new Web()
    console.info(w.run()) // 對(duì)象冒充可以繼承構(gòu)造函數(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. 原型鏈實(shí)現(xiàn)繼承
    function Web(name) {
    }
    Web.prototype = new Person()
    var w = new Web()
    console.info(w.run()) // 可以繼承構(gòu)造函數(shù)的屬性和方法   undefined在奔跑
    console.info(w.work()) // 可以繼承原型鏈上的屬性和方法 undefined在工作
    // 問題: 實(shí)例化子類的時(shí)候,無法給父類傳參
    
    
    1. 原型鏈+對(duì)象冒充組合繼承
    function Person(name) {
        this.name = name
        this.run = function () {
            return this.name + '在奔跑'
        }
    }
    Person.prototype.work = function () {
        return this.name + '在工作'
    }
    // 2. 原型鏈+對(duì)象冒充組合實(shí)現(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()) // 可以繼承構(gòu)造函數(shù)的屬性和方法
    console.info(w.work()) // 可以繼承原型鏈上的屬性和方法
    
    

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

  • 類的定義
    class 關(guān)鍵字

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

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

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

    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 語言
            // 當(dāng)前類里面的全局存在
            console.info(`靜態(tài)方法` + this.a++)
        }
    }
    Person.print()
    
    
  • 抽象類 繼承 多態(tài)

    1. 多態(tài):父類定義一個(gè)方法不去實(shí)現(xiàn),讓繼承它的子類去實(shí)現(xiàn) , 每個(gè)子類根據(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)準(zhǔn)備好狗糧,快來吃飯!'
          }
      }
      
    2. 抽象方法 - abstract 關(guān)鍵字
      ts 中的抽象類,是提供其他類繼承的基類/父類,不能直接實(shí)例化
      abstract關(guān)鍵字來定義抽象類和抽象方法,抽象類中的抽象方法不包含具體實(shí)現(xiàn)并且必須在派生類中實(shí)現(xiàn)
      作用: 抽象類和抽象方法用于定義標(biāo)準(zhǔn)

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

5.接口

interface 關(guān)鍵字

接口的作用:
在面向?qū)ο蟮木幊讨校涌谑且环N規(guī)范的定義
它定義了行為和動(dòng)作的規(guī)范,起到限制和規(guī)范的作用。
接口定義了某類所需遵守的規(guī)范,不關(guān)注類的內(nèi)部狀態(tài)數(shù)據(jù),也不關(guān)注類里面方法的實(shí)現(xiàn)細(xì)節(jié),它只規(guī)定類里必須提供某些方法,提供方法的類就可以滿足實(shí)際需要。
ts 中的接口類似于 java, 同時(shí)還增加了更靈活的接口類型,包括屬性、函數(shù)、可索引和類等。

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

    // 加密的函數(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ù)組、對(duì)象的約束(不常用)
    // 對(duì)數(shù)組的約束
    interface UserArr {
        [index: number]: string; // 索引值為 string 類型, index 為索引
    }
    let arr: UserArr = ['aaa', 'bbb']
    console.log(arr[0]) // 0 是指 index
    
    // 對(duì)對(duì)象的約束,  可索引接口
    interface UserObj {
        [index: string]: number; // 索引值為 number 類型, index 為索引
    }
    let obj1:UserObj = { name: 1, k: 2 }
    console.log(obj1.name) // name 是指 index
    
    
  • 類類型接口: 對(duì)類的約束 和 抽象類有的相似
    implements 關(guān)鍵字

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

    // 接口擴(kuò)展:接口可以繼承接口
    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.泛型

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

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

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

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

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

    // 比如有個(gè)最小堆算法,需要同時(shí)支持返回?cái)?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())
    

    泛類:泛型可以避免重復(fù)的代碼以及對(duì)不特定的數(shù)據(jù)類型的支持(類型校驗(yàn)),下面我們把類當(dāng)做參數(shù)的泛型類
    其可以去除重復(fù)代碼,可以對(duì)類型進(jìn)行校驗(yàn)

    /**
     * 1. 定義個(gè)類
     * 2. 把類作為參數(shù)來約束數(shù)據(jù)傳入的類型
     */
    /**
     * 需求:
     * 1. 定義一個(gè) User 的類,作用是映射數(shù)據(jù)庫字段
     * 2. 定義一個(gè) MysqlDb 的類,用于操作數(shù)據(jù)庫
     * 3. 把 User 類作為參數(shù)傳入到 MysqlDb 中
     * 
     * ` 非常像 java 中的 dto 層 `
     */
    class User {
        username: string | undefined;
        password: string | undefined;
    }
    
    // 操作數(shù)據(jù)庫的泛型類
    // 可以去除重復(fù)代碼,可以對(duì)類型進(jìn)行校驗(yàn)
    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 大差不差 , 都是為了面向?qū)ο筮M(jìn)行服務(wù)
    2. 這種復(fù)用性又讓我想起了原生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 的底層庫

需求分析如下:
功能:定義一個(gè)操作數(shù)據(jù)庫的庫, 支持 Mysql Mssql Mongodb
要求1:Mysql Mssql Mongodb 功能一樣, 都有 增刪改查(add,update,delet,get)方法
注意:約束統(tǒng)一的規(guī)范,以及代碼重用
解決方案:需要約束規(guī)范所以要定義接口,需要代碼重用所以用到泛型
1. 接口: 在面向?qū)ο蟮倪^程中,接口是一種規(guī)范的定義,它定義了行為和動(dòng)作的規(guī)范
2. 泛型: 通俗理解,泛型就是提高 類、接口、方法的復(fù)用性

interface DBI<T>{
    add(info: T): boolean;
    update(info: T, id: number): boolean;
    delete(id: number): boolean;
    get(id: number): any[];
}
// 定義一個(gè)操作 mysql 數(shù)據(jù)庫的類   tip: 實(shí)現(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.");
    }
}
// 操作用戶表 定義一個(gè) 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() // 沒有校驗(yàn)作用
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 模塊化 學(xué)習(xí)
ts 模塊的概念(官方):
· ts1.5發(fā)生了一些術(shù)語的變化,‘內(nèi)部模塊’ 稱為 ‘命名空間’
· ‘外部模塊’現(xiàn)在簡(jiǎn)稱為‘模塊’,模塊在其自身的作用域里執(zhí)行,而不是在全局作用域里,說明在一個(gè)模塊里的變量、函數(shù)、類等等在模塊外部不可見(不暴露、封裝性) ,除非 export , 需要使用的時(shí)候使用 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 進(jìn)行模塊化
 */
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[];
}
// 定義一個(gè)操作 mysql 數(shù)據(jù)庫的類   tip: 實(shí)現(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 }

```

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

Notes:

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

9. 命名空間

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

名稱 區(qū)分
命名空間 內(nèi)部模塊,主要用于組織代碼,避免命名沖突
模塊 ts 的外部模塊簡(jiǎn)稱,側(cè)重代碼的復(fù)用,一個(gè)模塊里可能會(huì)有多個(gè)命名空間

相同點(diǎn): 解決的都是代碼作用域的問題

利用 namespace 關(guān)鍵字:

``` 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ù)上,可以修改類的行為。
通俗理解: 裝飾器是一個(gè)方法,可以注入到類、方法、屬性參數(shù)來擴(kuò)展他們的功能。
常見的裝飾器有: 類裝飾器、屬性裝飾器、方法裝飾器、參數(shù)裝飾器
裝飾器的寫法: 普通裝飾器(無法傳參)、裝飾器工廠(可傳參)
裝飾器是過去幾年中 js 最大的成就之一,已經(jīng)是 es7 的標(biāo)準(zhǔn)特性之一

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

    1. 普通方法(無法傳參)
    function logClass(params: any) {
        console.info(params) // 當(dāng)前的類
    
        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)  // 當(dāng)前的類
                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. 類裝飾器替換類的構(gòu)造函數(shù)
    function logClass(target: any) {
        
        return class extends target () {
            // 相當(dāng)于重寫,因?yàn)槊總€(gè)屬性都需要 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)
    
  • 方法裝飾器
    方法裝飾器在運(yùn)行時(shí)傳入下列 3 個(gè)參數(shù):

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

    跟 es6 的相似

    // 方法裝飾器
    function get(params: any) {
        return function (target: any, methodName: any, desc: any) {
            // console.log(target) // 對(duì)于靜態(tài)成員來說是類的構(gòu)造函數(shù),對(duì)于實(shí)例成員是類的原型對(duì)象
            // console.log(methodName) // 成員的名字
            // console.log(desc) // 成員的屬性描述符
            
            // 修改裝飾器的方法, 把裝飾器方法里面?zhèn)魅氲乃袇?shù)改為 string 類型
            // 1. 保存當(dāng)前的方法
    
            let oMethod = desc.value  // 保存當(dāng)前方法
            // 修改當(dāng)前方法
            desc.value = function (...args: any[]) {
                args = args.map((val) {
                    return String(val)
                }) 
                console.log('裝飾器中轉(zhuǎn)換的形參:' , 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ù)裝飾器
    不常用, 其他裝飾器也可以實(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)
    

裝飾器順序:

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

四.案例 【 ts + angular 】

前提:

安裝angular/cli:
npm|cnpm install -g @angular/cli
驗(yàn)證:
ng version
新建項(xiàng)目:
ng new demo01

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

  1. 文件擴(kuò)展名不同,sass是以“.sass”后綴為擴(kuò)展名,而SCSS是以“.scss”后綴為擴(kuò)展名。
  2. 語法不同,sass是以嚴(yán)格的縮進(jìn)式語法規(guī)則來書寫,而scss的語法與css語法非常相似。

運(yùn)行項(xiàng)目:
ng serve --open

來自b站視頻觀看筆記,有錯(cuò)請(qǐng)指正!!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,527評(píng)論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,687評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,640評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,957評(píng)論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,682評(píng)論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 56,011評(píng)論 1 329
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,009評(píng)論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,183評(píng)論 0 290
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,714評(píng)論 1 336
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,435評(píng)論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,665評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,148評(píng)論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,838評(píng)論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,251評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,588評(píng)論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,379評(píng)論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,627評(píng)論 2 380

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