1. typescript由微軟開發的一款開源程式語言。
  2. ts是jacascript的超集,遵循ES6,ES5規範,ts擴充套件了js的語法。
  3. ts更像後端java,c#這樣的面向物件的語言,可以讓js開發大型的企業專案,
  4. 谷歌也大力支援ts的推廣,谷歌的angular2.x就是基於ts語法開發的
  5. 最新的Vue,React也繼承ts
  6. Nodejs框架Nestjs,midway中用的就是ts語法.
    目錄

基礎配置

安裝:npm i -g typescript

驗證是否安裝成功:tsc -v

Version 4.4.3

編譯ts:tsc index.ts(需要編譯的ts檔案)

ts開發工具 vscode自動編譯ts

  1. 建立tsconfig.json檔案

    tsc --init 生成配置檔案

    只改tsconfig:outdir:'./js'

  2. 自動生成js

    vscode-->終端-->執行任務-->typescript-->tsc:監視

一、ts中的型別

ts中為了是編寫的程式碼更加規範,更有利於維護,增加了型別校驗。

型別賦值錯誤會報錯,

主要型別有:

型別 名稱 解釋 寫法
布林型別 boolean true/false var flag:boolean=true
數值型別 number 整數/小數 var num:number=123
字串型別 string 字串 var str:string='123'
陣列型別 array 陣列 let arr:number[]=[1,2,3](只能放number型別)/let arr:Array=[1,2,3](只能放number型別,泛型定義)/
元組型別 tuple 陣列的一種可以指定數組裡每項型別 let arr:[string,number,boolean]=['ww',123,true]
列舉型別 enum enum 列舉名稱{識別符號[=整形常數]...} enum Flag{success:1,err:-1},var f:Flag=Flag.err
enum Color={red,blue,orage} ,var c:Color=Color.blue //c==1
任意型別 any 任意的值 let num:any='123'
null、undefined 其他型別子型別 var num:number
void型別 void 沒有任何型別,一般用於函式沒有返回值 function run():void {}
其他型別 never 包括null,undefined子型別,代表從不會出現的值 never的變數只能被never型別賦值

二、函式定義

ES5函式定義

函式宣告

  1. function run() {
  2. return 'run'
  3. }

匿名函式

  1. var run2 = function () { }

ts函式定義方法

1-函式宣告

  1. function run1(): string {
  2. return 'aa'
  3. }

2-匿名函式

  1. var fun2 = function (): number {
  2. return 123
  3. }

3-傳參

  1. function getInfo(name: string, age: number): string {
  2. return `${name}++${age}`
  3. }
  4. console.log(getInfo('asd', 22))

4-無返回值

```function run3(): void { }````

ts方法的可選引數

ES5方法的實參和形參可以不一樣,ts中必須一樣,如果不一樣需要配置可選引數

注意:可選引數必須配置到引數最後面,用?表示可選

  1. function getInfos(name: string, age?: number): string {
  2. return `${name}++${age}`
  3. }

預設引數

es5裡面沒法設定預設引數,es6和ts找那個可以設定預設引數

預設引數可以不傳,類似於可選引數

  1. function getInfo1(name: string, age: number = 20): string {
  2. return `${name}++${age}`
  3. }

剩餘引數

1-改進前寫法

  1. function sum(a: number, b: number, c: number, d: number): number {
  2. return a + b + c + d
  3. }

2-改進後

三點運算子 接收新傳過來的值

  1. function sum1(...arr: number[]): number {
  2. var sum = 0
  3. for (let i = 0; i < arr.length; i++) {
  4. sum += arr[i]
  5. }
  6. return sum
  7. }
  8. alert(sum1(1, 2, 3, 4))

另一種

  1. function sum2(a: number, ...arr: number[]): number {
  2. var sum = 0
  3. for (let i = 0; i < arr.length; i++) {
  4. sum += arr[i]
  5. }
  6. return a + sum
  7. }
  8. alert(sum2(1, 2, 3, 4))

函式過載

java中方法的過載,:兩個或以上同名函式,但他們引數不一樣,這是會出現函式過載情況

ts中的從在,通過為一個函式提供多個函式型別定義來實現多種功能的目的

ts為了箭筒es5和es6從在寫法和java中有區別

es5中出現同名方法,下面的會替換上面的方法

ts過載

  1. function getcon(name: string): string;
  2. function getcon(age: number): number;
  3. function getcon(name: string,age: number): string;
  4. function getcon(str: any,age?:number): any {
  5. if (typeof str == 'string') {
  6. return '姓名' + str
  7. } else {
  8. return '年齡' + str
  9. }
  10. }

三、物件的繼承

es5繼承

  1. es5裡面的建構函式

    1. function Person() {
    2. this.name = '張珊'
    3. this.age = 20
    4. this.run = function () {
    5. }
    6. }
  2. 原型鏈上的屬性會被多個例項共享,建構函式不會

    1. function Person() {
    2. this.name = '張珊'
    3. this.age = 20
    4. this.run = function () {
    5. }
    6. }
    7. Person.prototype.sex = '男'
    8. Person.prototype.work = function () {
    9. console.log(this.name)
    10. }
    11. Person.getInfo = function () {
    12. // 靜態方法
    13. }
    14. var p = new Person()
    15. p.work()
    16. // 呼叫靜態方法
    17. Person.getInfo()
  3. 建構函式與原型鏈增加方法

    1. function Person() {
    2. this.name = '張珊'
    3. this.age = 20
    4. this.run = function () {
    5. }
    6. }
    7. // 原型鏈上的屬性會被多個例項共享,建構函式不會
    8. Person.prototype.sex = '男'
    9. Person.prototype.work = function () {
    10. console.log(this.name)
    11. }
    12. Person.getInfo = function () {
    13. // 靜態方法
    14. }
    15. var p = new Person()
    16. p.work()
  4. 類裡面的靜態方法

    1. function Person() {
    2. this.name = '張珊'
    3. this.age = 20
    4. }
    5. // 定義靜態方法
    6. Person.getInfo = function () {
    7. }
    8. var p = new Person()
    9. // 呼叫靜態方法
    10. Person.getInfo()
  5. es5繼承

    原型鏈+物件冒充

    1. function Person(age) {
    2. this.name = '張珊'
    3. this.age = age
    4. }
    5. Person.prototype.sex = '男'
    6. Person.prototype.work = function () {
    7. console.log(this.name)
    8. }
    9. var p = new Person(18)
    10. // 物件冒充繼承---不可以繼承原型鏈的屬性和方法
    11. function Web(){
    12. Person.call(this)
    13. }
    14. // 原型鏈繼承-----例項化後沒法給父類傳參
    15. Web.prototype=new Person()
    16. var son=new Web()

ts繼承

1、ts定義類

  1. class Person {
  2. name: string; //屬性 省略了public關鍵詞
  3. constructor(n: string) {
  4. this.name = n
  5. }//建構函式,例項化類的時候觸發的方法
  6. run(): void { }
  7. }
  8. var p = new Person('aa')
  9. p.run()

2、ts中實現繼承

關鍵字:extends,super

子類與父類有相同方法,子類優先順序更高

  1. class Person1 {
  2. name: string; //屬性 省略了public關鍵詞
  3. constructor(n: string) {
  4. this.name = n
  5. }//建構函式,例項化類的時候觸發的方法
  6. run(): string {
  7. return `${this.name}是`
  8. }
  9. }
  10. class Webs extends Person1 {
  11. constructor(name: string) {
  12. super(name)//類似於初始化父類建構函式
  13. }
  14. work() { }
  15. }
  16. var w = new Webs('李四')

3、ts類裡面的修飾符

ts裡面定義屬性的時候給我們提供了三種修飾符

  • public :公有:在類裡面,子類,類外面都可以訪問

  • protected :保護型別:在類裡面,子類都可以訪問,類外面不可以訪問

  • private:私有:在類裡面可以訪問,子類,類外面都不可以訪問

  • 屬性不加修飾符預設公有public

  1. class Person2 {
  2. name: string; //屬性 省略了public關鍵詞
  3. private age: number
  4. constructor(n: string, a: number) {
  5. this.name = n
  6. this.age = a
  7. }//建構函式,例項化類的時候觸發的方法
  8. run(): string {
  9. return `${this.name}是`
  10. }
  11. }

4、靜態屬性 靜態方法

es5裡面的

  1. function Person(){}
  2. Person.run2=function(){}//靜態方法

ts裡面的

靜態方法無法呼叫類裡面的屬性,可以呼叫靜態屬性

  1. class Person3 {
  2. static sex = 'nam'//靜態屬性
  3. public name: string
  4. constructor(name: string) {
  5. this.name = name
  6. }
  7. run() { }
  8. static prient() {console.log(this.sex,Person3.sex) }//靜態方法
  9. }
  10. var p = new Person3('11')
  11. Person3.prient()//靜態方法呼叫

5、多型

父類定義一個方法不去實現,讓繼承它的子類去實現,每個子類有不同的表現

多型屬於繼承的一種表現

  1. class Animal{
  2. name:string
  3. constructor(name:string){
  4. this.name=name
  5. }
  6. eat(){
  7. console.log('吃的方法')
  8. }
  9. }
  10. class Dog extends Animal{
  11. constructor(name:string){
  12. super(name)
  13. }
  14. eat(){
  15. return this.name+'吃肉'
  16. }
  17. }
  18. class Cat extends Animal{
  19. constructor(name:string){
  20. super(name)
  21. }
  22. eat(){
  23. return this.name+'吃魚'
  24. }
  25. }

6、抽象方法

  • ts中的抽象類,他提供其他類整合的基類,不能直接被例項化
  • 用abstract關鍵字定義抽象類和抽象方法,抽象類中的抽象方法不包含具體實現並且必須在派生類中實現
  • abstract抽象方法只能放在抽象類裡面
  • 抽象類的子類必須事項抽象類裡面的方法

抽象類和抽象方法用來定義標準

標準:Animal這個類要求他的子類必須包含eat

  1. abstract class Animals{
  2. /**
  3. * name
  4. */
  5. public name:string
  6. constructor(name:string){
  7. this.name=name
  8. }
  9. abstract eat():any;
  10. }
  11. // 抽象類的子類必須事項抽象類裡面的方法
  12. class Dogs extends Animal{
  13. constructor(name:string){
  14. super(name)
  15. }
  16. eat(){
  17. return this.name+'吃肉'
  18. }
  19. }

四、介面

介面的作用:在面向物件的程式設計中,介面是一種規範的定義,它定義了行為和動作的規範,在程式設計裡面,換口起到一種限制和規範的作用。介面定義了某一批央所雷要遵守的現範,介面不關心這些類的內部狀態資料,也不關心這些類裡方法的實現細節,它只規定這批類裡必須提供某些方法,提供這些方法的類就可以滿足實際需要。typescrip中的介面類似於java,同時還增加了更靈活的介面型別,包括屬性面數、可索引和類

1.屬性介面

1、對json的約束

ts自定義方法傳入對json進行約束

  1. function prientLabel(labelInfo: { label: string }): void {
  2. }
  3. prientLabel({ name: 'aa' })//錯誤寫法
  4. prientLabel({ label: 'aa' })//正確寫法

2、對批量方法進行約束

介面:行為和動作規範,對批量方法進行約束

引數順序可以不一樣,但必須得有

關鍵詞:interface

  1. interface FullName {
  2. firstName: string;//注意;結束
  3. secondName: string;
  4. }
  5. function prientName(name: FullName) {
  6. // 必須傳入物件 firstName secoendName
  7. console.log(name.firstName, name.secondName)
  8. }
  9. var obj = { firstName: '1', secondName: 'jj', age: 1 }
  10. prientName(obj)
  11. prientName({ firstName: '1', secondName: 'jj', age: 1 })//傳age有問題

介面:可選屬性

  1. interface FullNames {
  2. firstName: string;//注意;結束
  3. secondName?: string;
  4. }

案例

  1. interface Config {
  2. type: string;
  3. url: string;
  4. data?: string
  5. dataType: string
  6. }
  7. function ajax(config: Config) {
  8. var xhr = new XMLHttpRequest()
  9. xhr.open(config.type, config.url, true)
  10. xhr.send(config.data)
  11. xhr.onreadystatechange = function () {
  12. if (xhr.readyState == 4 && xhr.status == 200) {
  13. if (config.dataType == 'json') {
  14. JSON.parse(xhr.response)
  15. }
  16. }
  17. }
  18. }
  19. ajax({
  20. type: 'get',
  21. url: 'http://..',
  22. data: '',
  23. dataType: 'json'
  24. })

2.函式型別介面

對傳入的引數以及返回值進行約束

加密函式型別介面

  1. interface encrypt {
  2. (ke: string, value: string): string
  3. }
  4. var md5: encrypt = function (key: string, value: string): string {
  5. return key + value
  6. }

3.可索引介面

陣列,物件的約束(不常用)

  1. interface UserArr {
  2. [index: number]: string
  3. }
  4. var arr: UserArr = ['11', '22']
  5. interface UserObj {
  6. [index: string]: string
  7. }
  8. var objw: UserObj = { name: '20' }

4.類型別介面

對類進行約束和抽象類有點相似

關鍵字:implements

  1. interface Animal1 {
  2. name: string;
  3. eat(str: string): void
  4. }
  5. class Dog implements Animal1 {
  6. name: string;
  7. constructor(name: string) {
  8. this.name = name
  9. }
  10. eat() {
  11. }
  12. }

5.介面擴充套件

介面可以繼承介面

  1. interface Animalss {
  2. eat(): void
  3. }
  4. interface Person extends Animalss {
  5. work(): void
  6. }
  7. class Son implements Person {
  8. name: string
  9. constructor(name: string) {
  10. this.name = name
  11. }
  12. eat() { }
  13. work() { }
  14. }
  15. class Progeammer {
  16. name: string
  17. constructor(name: string) {
  18. this.name = name
  19. }
  20. coding() { }
  21. }
  22. class web extends Progeammer implements Person {
  23. constructor(name: string) {
  24. super(name)
  25. }
  26. eat() { }
  27. work() { }
  28. coding() { }
  29. }

五、泛型

  • 泛型,軟體工程中,我們不僅要建立一致的定義良好的API,同時也要考慮可重用性。 元件不僅能夠支援當前的資料型別,同時也能支援未來的資料型別,這在建立大型系統時為你提供了十分靈活的功能。
  • 在像C#和Java這樣的語言中,可以使用泛型來建立可重用的元件,一個元件可以支援多種型別的資料。這樣使用者就可以以自己的資料型別來使用元件。
  • 通俗理解:泛型就是解決類 接日 方法的複用性、以及對不特定資料型別的支援

    普通寫法

    只能返回string型別的資料
  1. function getData(value:string):string{return value}

返回多種型別的資料 any可以解決這種問題(any放棄了型別檢查)

  1. function getData1(value:any):any{return value}

1.泛型定義

  1. 傳入和返回型別相同
  2. 可以支援不特定的資料型別
  3. T表示泛型,具體什麼型別是呼叫這個方法的時候決定的
    1. function getData2<T>(value:T):T{return value}
    2. getData2<number>(123)
    3. // getData2<number>(‘kkk’)/* 錯誤寫法 */

2.泛型類

普通寫法

  1. class Minclass{
  2. public list:number[]=[]
  3. add(num:number){
  4. this.list.push(num)
  5. }
  6. min():number{
  7. var min=this.list[0]
  8. for (let i = 0; i < this.list.length; i++) {
  9. if(min>this.list[i]){
  10. min=this.list[i]
  11. }
  12. }
  13. return min
  14. }
  15. }

泛型類寫法

  1. class Minclass1<T>{
  2. public list:T[]=[]
  3. add(num:T):void{
  4. this.list.push(num)
  5. }
  6. min():T{
  7. var min=this.list[0]
  8. for (let i = 0; i < this.list.length; i++) {
  9. if(min>this.list[i]){
  10. min=this.list[i]
  11. }
  12. }
  13. return min
  14. }
  15. }
  16. var m1=new Minclass1<number>()

3.泛型介面

  1. interface ConfigFn{
  2. (value:string,value2:string):string
  3. }
  4. var setData:ConfigFn=function(val:string,val2:string):string{
  5. return val+val2
  6. }
  1. interface ConfigFn1{
  2. <T>(value:T,value2:T):T
  3. }
  4. var setData1:ConfigFn1=function<T>(val:T,val2:T):T{
  5. return val
  6. }
  7. setData1<string>('123','11')
  1. interface ConfigFn2<T>{
  2. (value:T):T
  3. }
  4. function getData6<T>(val:T):T{
  5. return val
  6. }
  7. var myGetData:ConfigFn2<string>=getData6
  8. myGetData('ll')

案例

  1. class User{
  2. name:string|undefined;
  3. pass:string|undefined
  4. }
  5. class Mysql{
  6. add(user:User):boolean{
  7. return true
  8. }
  9. }
  10. var u=new User()
  11. u.name='zhang'
  12. u.pass='123'
  13. var db=new Mysql()
  14. db.add(u)

泛型封裝

  1. class User1{
  2. name:string|undefined;
  3. pass:string|undefined
  4. }
  5. class Mysql1<T>{
  6. add(info:T):boolean{
  7. return true
  8. }
  9. }
  10. var u=new User1()
  11. u.name='zhang'
  12. u.pass='123'
  13. var db1=new Mysql1<User1>()
  14. db1.add(u)

案例

功能:定義一個操作資料庫的庫支援 Mysql MssqlMongoDb

要求1:Mysql MsSqlMongoDb功能一樣都有 add update delete get方法

注意:約束統一的規範、以及程式碼重用

解決方案:需要約束規範所以要定義介面,需要程式碼重用所以用到泛型

1、介面:在面向物件的程式設計中,介面是一種規範的定義,它定義了行為和動作的規範

2、泛型 通俗理解:泛型就是解決類 介面 方法的複用性、

  1. interface DBI<T>{
  2. add(info:T):boolean;
  3. update(info:T,id:number):boolean
  4. delete(id:number):boolean
  5. get(id:number):any[]
  6. }
  7. // 定義一個操作mysql資料庫的類
  8. class MysqlDb<T> implements DBI<T>{
  9. add(info: any): boolean {
  10. throw new Error("Method not implemented.")
  11. }
  12. update(info: any, id: number): boolean {
  13. throw new Error("Method not implemented.")
  14. }
  15. delete(id: number): boolean {
  16. throw new Error("Method not implemented.")
  17. }
  18. get(id: number): any[] {
  19. throw new Error("Method not implemented.")
  20. }
  21. }
  22. // 操作使用者表 定義一個User類和資料庫對映表
  23. class Users{
  24. name:string|undefined
  25. pass:string|undefined
  26. }
  27. var u=new Users()
  28. u.name='00'
  29. u.pass='ii'
  30. var omysql=new MysqlDb<Users>()
  31. omysql.add(u)

六、模組

  • 模組的的概念(官方):

    1. 關於木語的一點說明:請務必注意一點,TypeScript 1.5裡木語名已經發生了變化。“內部模組”現在稱做“名稱空間”。外部模組“現在則簡稱為“模組#模組在且自身的作用域裡執行,而不是在全域性作用域裡:
    2. 這意味著定義在一個模組裡的變數,因數,類等等在模組外部是不可見的,除非你明確地使用export形式之一匯出它們。相反,如果想使用其它模組匯出的變數,國數,類,介面等的時候,你必須要匯入它們,可以使用 import形式之一。
  • 模組的概念(自己理解):
    1. 我們可以把一些公共的功能單獨抽離成一個檔案作為一個模組。
    2. 模組裡面的變數 函式 類等預設是私有的,如果我們要在外部訪問模組裡面的資料(變數、函式、類),我們要要通過export暴露模組裡面的資料(變數、團數、類。。》。
    3. 暴露後我們通過 import 引入模組就可以使用模組裡面暴露的資料(變數、函式、類...)。

自定義模組

  1. var dburl='xxx'
  2. export function getData():any[]{
  3. return[{
  4. title:'123'
  5. },{
  6. title:'456'
  7. }]
  8. }

匯入

  1. import {getData} from './db'
  2. getData()

export default 預設匯出

每個模組都可以有一個default匯出,預設匯出使用default關鍵字標記;並且一個模組只能夠有一個default匯出,需要使用一個特殊的匯入形式

七、名稱空間

  • 在程式碼量較大的情況下,為了避免各種變數命名相沖突,可將相似功能的函式、類、介面等放置到名稱空間內
  • 同Java的包、.Net的名稱空間一樣,TypeScript的名稱空間可以將程式碼包裹起來,只對外暴露需要在外部訪問的物件。名稱空間內的物件通過export關鍵字對外暴露。

名稱空間和模組的區別

  • 名稱空間:內部模組,主要用於組織程式碼,避免命名衝突。
  • 模 塊:ts的外部模組的簡稱,側重程式碼的複用,一個模組裡可能會有多個名稱空間。
  1. namespace A{
  2. interface Animal {
  3. name: string;
  4. eat(): void;
  5. }
  6. export class Dog implements Animal {
  7. name: string;
  8. constructor(theName: string) {
  9. this.name = theName;
  10. }
  11. eat() {
  12. console.log(`${this.name} 在吃狗糧。`);
  13. }
  14. }
  15. export class Cat implements Animal {
  16. name: string;
  17. constructor(theName: string) {
  18. this.name = theName;
  19. }
  20. eat() {
  21. console.log(`${this.name} 吃貓糧。`);
  22. }
  23. }
  24. }
  1. namespace B{
  2. interface Animal {
  3. name: string;
  4. eat(): void;
  5. }
  6. export class Dog implements Animal {
  7. name: string;
  8. constructor(theName: string) {
  9. this.name = theName;
  10. }
  11. eat() {
  12. console.log(`${this.name} 在吃狗糧。`);
  13. }
  14. }
  15. export class Cat implements Animal {
  16. name: string;
  17. constructor(theName: string) {
  18. this.name = theName;
  19. }
  20. eat() {
  21. console.log(`${this.name} 在吃貓糧。`);
  22. }
  23. }
  24. }
  25. var c=new B.Cat('小花');
  26. c.eat();

封裝:模組化+名稱空間

  1. export namespace A{
  2. interface Animal {
  3. name: string;
  4. eat(): void;
  5. }
  6. export class Dog implements Animal {
  7. name: string;
  8. constructor(theName: string) {
  9. this.name = theName;
  10. }
  11. eat() {
  12. console.log(`${this.name} 在吃狗糧。`);
  13. }
  14. }
  15. export class Cat implements Animal {
  16. name: string;
  17. constructor(theName: string) {
  18. this.name = theName;
  19. }
  20. eat() {
  21. console.log(`${this.name} 吃貓糧。`);
  22. }
  23. }
  24. }
  1. import {A} from './modules/animal';
  2. var d=new A.Dog('小黑');
  3. d.eat();

八、裝飾器

屬性裝飾器

裝飾器工廠

裝飾器定義

  • 裝飾器:裝飾器是一種特殊型別的宣告,它能夠被附加到類宣告,方法,屬性或引數上,可以修改類的行為。
  • 通俗的講裝飾器就是一個方法,可以注入到類、方法、屬性引數上來擴充套件類、屬性、方法、引數的功能。
  • 常見的裝飾器有:類裝飾器、屬性裝飾器、方法裝飾器、引數裝飾器
  • 裝飾器的寫法:普通裝飾器(無法傳參) 、 裝飾器工廠(可傳參)
  • 裝飾器是過去幾年中js最大的成就之一,已是Es7的標準特性之一

類裝飾器

類裝飾器:類裝飾器在類宣告之前被宣告(緊靠著類宣告)。 類裝飾器應用於類建構函式,可以用來監視,修改或替換類定義。 傳入一個引數

類裝飾器:普通裝飾器(無法傳參)

  1. function logClass(params:any){
  2. console.log(params);
  3. // params 就是當前類
  4. params.prototype.apiUrl='動態擴充套件的屬性';
  5. params.prototype.run=function(){
  6. console.log('我是一個run方法');
  7. }
  8. }
  9. @logClass
  10. class HttpClient{
  11. constructor(){
  12. }
  13. getData(){
  14. }
  15. }
  16. var http:any=new HttpClient();
  17. console.log(http.apiUrl);
  18. http.run();

類裝飾器:裝飾器工廠(可傳參)

  1. function logClass(params:string){
  2. return function(target:any){
  3. console.log(target);
  4. console.log(params);
  5. target.prototype.apiUrl=params;
  6. }
  7. }
  8. @logClass('http://www.itying.com/api')
  9. class HttpClient{
  10. constructor(){
  11. }
  12. getData(){
  13. }
  14. }
  15. var http:any=new HttpClient();
  16. console.log(http.apiUrl);

類裝飾器案例

下面是一個過載建構函式的例子。

裝飾器表示式會在執行時當作函式被呼叫,類的建構函式作為其唯一的引數。

如果類裝飾器返回一個值,它會使用提供的建構函式來替換類的宣告。

  1. function logClass(target:any){
  2. console.log(target);
  3. return class extends target{
  4. apiUrl:any='我是修改後的資料';
  5. getData(){
  6. this.apiUrl=this.apiUrl+'----';
  7. console.log(this.apiUrl);
  8. }
  9. }
  10. }
  11. @logClass
  12. class HttpClient{
  13. public apiUrl:string | undefined;
  14. constructor(){
  15. this.apiUrl='我是建構函式裡面的apiUrl';
  16. }
  17. getData(){
  18. console.log(this.apiUrl);
  19. }
  20. }
  21. var http=new HttpClient();
  22. http.getData();

屬性裝飾器

屬性裝飾器表示式會在執行時當作函式被呼叫,傳入下列2個引數:

  1. 對於靜態成員來說是類的建構函式,對於例項成員是類的原型物件。
  2. 成員的名字。

類裝飾器

  1. function logClass(params:string){
  2. return function(target:any){
  3. // console.log(target);
  4. // console.log(params);
  5. }
  6. }

屬性裝飾器

  1. function logProperty(params:any){
  2. return function(target:any,attr:any){
  3. console.log(target);
  4. console.log(attr);
  5. target[attr]=params;
  6. }
  7. }
  8. @logClass('xxxx')
  9. class HttpClient{
  10. @logProperty('http://itying.com')
  11. public url:any |undefined;
  12. constructor(){
  13. }
  14. getData(){
  15. console.log(this.url);
  16. }
  17. }
  18. var http=new HttpClient();
  19. http.getData();

方法裝飾器

它會被應用到方法的 屬性描述符上,可以用來監視,修改或者替換方法定義。

方法裝飾會在執行時傳入下列3個引數:

2. 對於靜態成員來說是類的建構函式,對於例項成員是類的原型物件。

2. 成員的名字。

3. 成員的屬性描述符。

方法裝飾器一

  1. function get(params:any){
  2. return function(target:any,methodName:any,desc:any){
  3. console.log(target);
  4. console.log(methodName);
  5. console.log(desc);
  6. target.apiUrl='xxxx';
  7. target.run=function(){
  8. console.log('run');
  9. }
  10. }
  11. }
  12. class HttpClient{
  13. public url:any |undefined;
  14. constructor(){
  15. }
  16. @get('http://www.itying,com')
  17. getData(){
  18. console.log(this.url);
  19. }
  20. }
  21. var http:any=new HttpClient();
  22. console.log(http.apiUrl);
  23. http.run();

方法裝飾器二

  1. function get(params:any){
  2. return function(target:any,methodName:any,desc:any){
  3. console.log(target);
  4. console.log(methodName);
  5. console.log(desc.value);
  6. //修改裝飾器的方法 把裝飾器方法裡面傳入的所有引數改為string型別
  7. //1、儲存當前的方法
  8. var oMethod=desc.value;
  9. desc.value=function(...args:any[]){
  10. args=args.map((value)=>{
  11. return String(value);
  12. })
  13. oMethod.apply(this,args);
  14. }
  15. }
  16. }
  17. class HttpClient{
  18. public url:any |undefined;
  19. constructor(){
  20. }
  21. @get('http://www.itying,com')
  22. getData(...args:any[]){
  23. console.log(args);
  24. console.log('我是getData裡面的方法');
  25. }
  26. }
  27. var http=new HttpClient();
  28. http.getData(123,'xxx');

方法引數裝飾器

引數裝飾器表示式會在執行時當作函式被呼叫,可以使用引數裝飾器為類的原型增加一些元素資料 ,傳入下列3個引數:

  1. 對於靜態成員來說是類的建構函式,對於例項成員是類的原型物件。
  2. 方法的名字。
  3. 引數在函式引數列表中的索引。
  1. function logParams(params:any){
  2. return function(target:any,methodName:any,paramsIndex:any){
  3. console.log(params);
  4. console.log(target);
  5. console.log(methodName);
  6. console.log(paramsIndex);
  7. target.apiUrl=params;
  8. }
  9. }
  10. class HttpClient{
  11. public url:any |undefined;
  12. constructor(){
  13. }
  14. getData(@logParams('xxxxx') uuid:any){
  15. console.log(uuid);
  16. }
  17. }
  18. var http:any = new HttpClient();
  19. http.getData(123456);
  20. console.log( http.apiUrl);

裝飾器執行順序

屬性》方法》方法引數》類

如果有多個同樣的裝飾器,它會先執行後面的

  1. function logClass1(params:string){
  2. return function(target:any){
  3. console.log('類裝飾器1')
  4. }
  5. }
  6. function logClass2(params:string){
  7. return function(target:any){
  8. console.log('類裝飾器2')
  9. }
  10. }
  11. function logAttribute1(params?:string){
  12. return function(target:any,attrName:any){
  13. console.log('屬性裝飾器1')
  14. }
  15. }
  16. function logAttribute2(params?:string){
  17. return function(target:any,attrName:any){
  18. console.log('屬性裝飾器2')
  19. }
  20. }
  21. function logMethod1(params?:string){
  22. return function(target:any,attrName:any,desc:any){
  23. console.log('方法裝飾器1')
  24. }
  25. }
  26. function logMethod2(params?:string){
  27. return function(target:any,attrName:any,desc:any){
  28. console.log('方法裝飾器2')
  29. }
  30. }
  31. function logParams1(params?:string){
  32. return function(target:any,attrName:any,desc:any){
  33. console.log('方法引數裝飾器1')
  34. }
  35. }
  36. function logParams2(params?:string){
  37. return function(target:any,attrName:any,desc:any){
  38. console.log('方法引數裝飾器2')
  39. }
  40. }
  41. @logClass1('http://www.itying.com/api')
  42. @logClass2('xxxx')
  43. class HttpClient{
  44. @logAttribute1()
  45. @logAttribute2()
  46. public apiUrl:string | undefined;
  47. constructor(){
  48. }
  49. @logMethod1()
  50. @logMethod2()
  51. getData(){
  52. return true;
  53. }
  54. setData(@logParams1() attr1:any,@logParams2() attr2:any,){
  55. }
  56. }
  57. var http:any=new HttpClient();