ts學(xué)習(xí)筆記

配置

  • tsc --init 生成tsconfig.json
  • vscode 任務(wù)-運(yùn)行任務(wù) tsc:監(jiān)視-tsconfig.json

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

  • boolean, number, string, array, null, undefied, void

  • 元組類型tuple

    let tuple:[number, string] = [1, 's']
    
  • 枚舉類型enum

    enum Color {
        red,
        blue,
        yellow = 5,
    }
    let color:Color = Color.yellow // 5
    color = Color.yellow // 0浪慌, 未賦值則輸出下標(biāo)
    
  • 任意類型any

  • null和undefined是其他(never)類型的子類型

  • void類型: ts中void類型表示沒(méi)有任何類型,一般用于定義方法時(shí)朴则,方法沒(méi)有返回值

  • never類型:其他類型(null和undefined)的子類型

函數(shù)

// 函數(shù)聲明
function run():string {
    return '123'
}

// 匿名表達(dá)式
var run2 = function():string {
    return '123'
}

// ts中定義方法傳參
function getInfo(name: string, age: number):string {
    return `${name}:${age}`
}

// 方法可選參數(shù)(age可傳权纤,可不傳)
// 可選參數(shù)要放在所有參數(shù)的最后
function getInfo(name: string, age?: number):string {
    if (age) {
        return `${name}:${age}`
    }
    return `${name}`
}

// 默認(rèn)參數(shù)
function getInfo(name: string, age: number = 20):string {
    if (age) {
        return `${name}:${age}`
    }
    return `${name}`
}

// 剩余參數(shù)
function sum(a: number, b:number, c:number, d:number):number {
    return a + b + c + d;
}
可改為
function sum(...res: number[]):number {
  return res.reduce((acc, cur) => acc + cur, 0)
}

// ts函數(shù)重載
function getInfo(name: string): string;
function getInfo(age: number): number;

function getInfo(arg: any): any {
  return 123;
}
// 箭頭函數(shù)

ts中的類

  • 類的定義、繼承
// es5
function Person(name) {
  this.name = name;
  this.run = function () {
    console.log(this.name)
  }
}
var p = new Person('張三')
p.run()


// ts中定義類
class Person {
  name: string; // 屬性乌妒,省略了public關(guān)鍵詞
  constructor(name:string) { // 構(gòu)造函數(shù)汹想,實(shí)例化類時(shí)觸發(fā)的方法
    this.name = name;
  }
  getName():string {
    return this.name
  }
  setName(name: string):void{
    this.name = name
  }
}

var p = new Person('張三')
p.setName('李四')
alert(p.getName())

// ts中實(shí)現(xiàn)繼承 extends, super

class Person {
  name: string; // 屬性,省略了public關(guān)鍵詞
  constructor(name:string) { // 構(gòu)造函數(shù)撤蚊,實(shí)例化類時(shí)觸發(fā)的方法
    this.name = name;
  }
  run():string {
    return `${this.name} is running`
  }
}

class Web extends Person {
  constructor(name: string) {
    super(name)
  }
}

var w = new Web('lisi')
console.log(w.run())

// ts中繼承的探討
class Person {
  name: string; // 屬性古掏,省略了public關(guān)鍵詞
  constructor(name:string) { // 構(gòu)造函數(shù),實(shí)例化類時(shí)觸發(fā)的方法
    this.name = name;
  }
  run():string {
    return `${this.name} is running`
  }
}

class Web extends Person {
  constructor(name: string) {
    super(name)
  }
  run():string {
    return '子類' //父類中也有同名方法侦啸,則調(diào)用子類的方法
  }
  work() {
    alert(`${this.name}在工作`) // this指向web實(shí)例
  }
}

var w = new Web('lisi')
console.log(w.run())

類里的修飾符

  • ts里定義屬性的時(shí)候槽唾,給我們提供了三種修飾符
/* 
    public:公有 在類里面,子類和類外面都可以訪問(wèn)
    protected:保護(hù)類型 在類里面匹中、子類里面可以訪問(wèn)夏漱,在類外部沒(méi)法訪問(wèn)
    private:私有 在類里面可以訪問(wèn),子類和類外部都沒(méi)法訪問(wèn)
*/

// public
// 屬性不加任何修飾符為public

// 類外部訪問(wèn)公有屬性
class Person {
  public name: string;
  constructor(name:string) {
    this.name = name;
  }
}
var p = new Person('lala');
console.log(p.name)

// protected

// 在子類中訪問(wèn)
class Person {
  protected name: string; // 屬性顶捷,省略了public關(guān)鍵詞
  constructor(name:string) { // 構(gòu)造函數(shù)挂绰,實(shí)例化類時(shí)觸發(fā)的方法
    this.name = name;
  }
}
class Web extends Person {
  constructor(name: string) {
    super(name)
  }
  run():string {
    return `${this.name}lalalla`
  }
}
var w = new Web('ab');
console.log(w.run())

// private 只能在類內(nèi)部訪問(wèn)
class Person {
  private name: string; // 屬性,省略了public關(guān)鍵詞
  constructor(name:string) { // 構(gòu)造函數(shù),實(shí)例化類時(shí)觸發(fā)的方法
    this.name = name;
  }
}


靜態(tài)屬性 靜態(tài)方法

  • es5
// 實(shí)例方法
function Person() {
  this.run1 = function() {
    ...
  }
}

// 靜態(tài)方法
Person.run2 = function() {

}

// 靜態(tài)屬性
Person.name = 'lalal'


var p = new Person();
p.run1()

Person.run2()
  • 已經(jīng)有實(shí)例方法葵蒂,為啥要有靜態(tài)方法

    // jquery
    
    function $(element) {
        return new Base(element)
    }
    
    function Base (element) {
        this.element = document.getElementById(element);
        this.css = function (attr, val) {
            this.element.style.attr = val
        }
    }
    // 實(shí)例方法
    $('#box').css('color', 'red')
    // 靜態(tài)方法
    $.get('url', function() {...})
    
  • ts里靜態(tài)方法和屬性

class Person {
  public name: string
  public age: number = 20
  // 靜態(tài)屬性
  static sex: string = '男'
  constructor(name:string) {
    this.name = name;
  }
  // 實(shí)例方法
  run() {
    alert(`${this.name}is running`)
  }
  work() {
    alert(`${this.name}is working`)
  }
  // 靜態(tài)方法 里面沒(méi)法直接調(diào)用類里面的屬性=徊ァ!践付!
  static print() {
    alert(`print+${Person.sex}`)
  }
}

Person.print()

多態(tài) :父類定義一個(gè)方法不去實(shí)現(xiàn)秦士,讓繼承他的子類去實(shí)現(xiàn),每一個(gè)子類有不同的表現(xiàn)

  • 多態(tài)屬于繼承
class Animal {
  name: string
  constructor(name: string) {
    this.name = name
  }
  eat() { // 具體的內(nèi)容永高,讓繼承他的子類去實(shí)現(xiàn)隧土,每個(gè)子類有不同表現(xiàn)
    console.log('eat')
  }
}

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 + '吃魚'
  }
}

var cat = new Cat('cattie')
alert(cat.eat())

ts中的抽象類,提供其他類繼承的基類命爬,不能直接被實(shí)例化

  • 用abstract關(guān)鍵字定義抽象類和抽象方法曹傀,抽象類中的抽象方法不包含具體實(shí)現(xiàn)并必須在派生類中實(shí)現(xiàn)
  • abstract抽象方法只能放在抽象類里面
  • 抽象類和抽象方法用來(lái)定義標(biāo)準(zhǔn)
// Animal類的子類必須包含eat方法
abstract class Animal {
  public name: string;
  constructor(name:string) {
    this.name = name
  }
  abstract eat():any;
}

// 抽象類的子類必須實(shí)現(xiàn)抽象類里的抽象方法
class Dog extends Animal {
  constructor(name:string) {
    super(name)
  }
  eat() {
    return this.name + 'something'
  }
}

var d = new Dog('abctest+')
alert(d.eat())

ts中的接口

  • 定義標(biāo)準(zhǔn)(包括屬性,函數(shù)饲宛,可索引皆愉, 類等)

屬性接口 對(duì)json的約束

// 接口 行為和動(dòng)作的規(guī)范 對(duì)批量方法傳入?yún)?shù)進(jìn)行約束
// 對(duì)傳入對(duì)象的約束, 屬性接口
interface FullName {
  firstName: string; // 注意MЭ佟幕庐!分號(hào)結(jié)束
  secondName: string;
}

function printName(name: FullName) {
  // 必須傳入對(duì)象,必須包含fistName家淤,secondName
  console.log(`${name.firstName} ${name.secondName}`)
  // console.log(`${name.firstName} ${name.secondName} ${name.age}`) // name.age 報(bào)錯(cuò)
}

// 直接傳入?yún)?shù)异剥,則有且僅有firstName和secondName,否則報(bào)錯(cuò)
// printName({ firstName: 'zhang', secondName: 'san' age: 20 }) // age報(bào)錯(cuò)

// 定義在外面 再傳入媒鼓,則必須包含firstName和secondName届吁,多的參數(shù)也行, 但在方法里調(diào)用fullName不存在的屬性也會(huì)報(bào)錯(cuò)
const obj = {
  firstName: 'zhang',
  secondName: 'san',
  age: 20
}

printName(obj)
  • 接口 可選屬性
interface FullName {
  firstName: string;
  secondName?: string;
}

函數(shù)類型接口: 對(duì)方法傳入的參數(shù),以及返回值進(jìn)行約束 (可批量約束)

interface encrypt {
  (key: string, val: string):string
}

var md5:encrypt = function(key: string, val: string):string {
  return `${key} + ${val}`
}

console.log(md5('test', '123'))

可索引接口绿鸣,對(duì)數(shù)組/對(duì)象的約束

// 可索引接口 對(duì)數(shù)組的約束
interface UserArr {
  [index: number]: string
}

var arrTest: UserArr = ['123', '112']

console.log(arrTest[0])

// 可索引接口 對(duì)對(duì)象的約束
interface UserObj {
  [index: string]: string
}

var usrObj:UserObj = {
  name: '20'
}

console.log(usrObj.name)

類類型接口

// 類類型接口:對(duì)類的約束 和抽象類有點(diǎn)類似
interface Animal {
  name: string;
  eat(str: String):void;
}

class Dog implements Animal {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
  // 必須有eat方法疚沐,eat方法可不傳參數(shù)
  eat() {
    console.log(this.name + '吃糧食')
  }
}

var d = new Dog('xxiaohei')
d.eat()

class Cat implements Animal {
  name: string;
  constructor(name: string) {
    this.name = name
  }
  eat(food: string) {
    console.log(`${this.name} + ${food}`)
  }
}

var c = new Cat('miaomiao')
c.eat('laoshu')

接口的擴(kuò)展、接口的繼承(接口可以繼承接口)

// 例子一
interface Animal {
  eat():void
}

interface Person extends Animal {
  work():void
}

class Web implements Person {
  public name: string;
  constructor(name:string) {
    this.name = name
  }
  eat() {
    console.log(`${this.name} --- chi`)
  }
  work() {
    console.log(`${this.name} --- work`)
  }
}

var ww = new Web('webbbb')
ww.eat()
ww.work()

// 例子二 繼承 + 實(shí)現(xiàn)(接口擴(kuò)展)
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} + coding... + ${code}`)
  }

}

class Web extends Programmer implements Person {
  constructor(name:string) {
    super(name)
  }
  eat() {
    console.log(`${this.name} --- chi`)
  }
  work() {
    console.log(`${this.name} --- work`)
  }
}

var ww = new Web('webbbb')
ww.eat()
ww.work()
ww.coding('ts')

泛型

  • 解決類 潮模,接口亮蛔,方法的復(fù)用性, 以及對(duì)不特定數(shù)據(jù)類型的支持
  • 泛型可以支持不特定的類型數(shù)據(jù),要求:傳入的參數(shù)和返回的參數(shù)一致

泛型的定義擎厢,泛型函數(shù)

// T表示泛型 具體什么類型是調(diào)用這個(gè)方法的時(shí)候決定的
function getData<T>(value:T):T {
    return value
}
// function getData<T>(value:T):any {
//   return 'test'
// }

// getData<Number>('test');  錯(cuò)誤寫法
getData<Number>(123); // 參數(shù)必須是number

泛型類

// 最小堆算法究流,需要同時(shí)支持返回?cái)?shù)字和字符串兩種類型,通過(guò)類的泛型來(lái)實(shí)現(xiàn)
class MinClass<T> {
  public list: T[] = []
  add(num:T) {
    this.list.push(num)
  }
  min():T {
    var minNum = this.list[0]
    for (let i = 0; i < this.list.length; i++) {
      if (this.list[i] < minNum) {
        minNum = this.list[i]
      }
    }
    return minNum
  }
}

var m = new MinClass<number>() // 實(shí)例化類动遭,且制定T代表number

m.add(2)
m.add(3)
m.add(4)

alert(m.min())

var m2 = new MinClass<string>()
m2.add('44')
m2.add('a')
m2.add('v')
alert(m2.min())

泛型接口

// 1. 第一種定義泛型接口的方法
interface ConfigFn {
  <T>(val:T):T
}

var getData:ConfigFn = function<T>(value: T) {
  return value
}

getData<string>('123')

// 2.第二種定義泛型接口的方法
interface ConfigFn<T> {
  (val:T):T;
}

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

var myGetData:ConfigFn<string> = getData;

myGetData('20')

把類作為參數(shù)類型的泛型類

  1. 先定義個(gè)類
  2. 把類作為參數(shù)來(lái)約束數(shù)據(jù)傳入的類型

功能一

class User {
  username: string | undefined;
  password: string | undefined;
}

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

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

var db = new MysqlDb()
db.add(u)

功能二

class ArticleCate {
  title: string | undefined;
  desc: string | undefined;
  status: number | undefined;
}
class MysqlDb {
  add(info: ArticleCate): boolean {
    console.log(info)
    return true
  }
}

var a = new ArticleCate()
a.title = '國(guó)內(nèi)'
a.desc = '國(guó)內(nèi)新聞'
a.status = 1

var DB = new MysqlDb()
DB.add(a)

但mySqlDb重復(fù)封裝了芬探,通過(guò)泛型解決

// 操作數(shù)據(jù)庫(kù)的泛型類
class MysqlDb <T> {
  add(info: T): boolean {
    console.log(info)
    return true
  }
  update(info: T, id: number):boolean {
    console.log(info)
    console.log(id)
    return true
  }
}

// 1.定義一個(gè)user類和數(shù)據(jù)庫(kù)進(jìn)行映射
class User {
  username: string | undefined;
  password: string | undefined;
}

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

var DB = new MysqlDb<User>()

DB.add(u)

// 1.定義一個(gè)ArticleCate類和數(shù)據(jù)庫(kù)進(jìn)行映射
class ArticleCate {
  title: string | undefined;
  desc: string | undefined;
  status: number | undefined;
  constructor(params: {
    title?: string,
    desc?: string,
    status?: number ,
  }) {
    this.title = params.title
    this.desc = params.desc
    this.status = params.status
  }
}

var a = new ArticleCate({
  title: '分類',
  desc: '111'
})

var DB2 = new MysqlDb<ArticleCate>()

DB2.add(a)
DB2.update(a, 2)

ts類型,接口厘惦,類偷仿,泛型綜合使用

interface DBI<T> {
  add(info: T):boolean;
  update(info: T, id: number):boolean;
  delete():boolean;
  get(id: number): any[]
}

// 定義一個(gè)操作mySql數(shù)據(jù)庫(kù)的類 注意:要實(shí)現(xiàn)泛型接口,這個(gè)類也應(yīng)該是一個(gè)泛型類
class MysqlDb<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(): boolean {
    throw new Error("Method not implemented.");
  }
  get(id: number): any[] {
    var list = [
      {
        title: 'xxxx',
        desc: 'xxx1'
      },
      {
        title: 'xxxx',
        desc: 'xxx1'
      },
    ]
    return list
  }
}

// 定義一個(gè)操作mySql數(shù)據(jù)庫(kù)的類 注意:要實(shí)現(xiàn)泛型接口,這個(gè)類也應(yīng)該是一個(gè)泛型類
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(): boolean {
    throw new Error("Method not implemented.");
  }
  get(id: number): any[] {
    var list = [
      {
        title: 'xxxx',
        desc: 'xxx1'
      },
      {
        title: 'xxxx',
        desc: 'xxx1'
      },
    ]
    return list
  }
}

// 操作用戶表 定義一個(gè)user類和數(shù)據(jù)表的映射
class User {
  username: string | undefined;
  password: string | undefined;
}

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

var oMySql = new MysqlDb<User>(); // 用類約束傳入?yún)?shù)的合法性
oMySql.add(u)
console.log(oMySql.get(4))


var oMsSql = new MssqlDb<User>()
oMsSql.add(u)
console.log(oMsSql.get(1))

ts 模塊化封裝

模塊的定義酝静,引用

// db.ts
var dbUrl = 'xxx'

function getData():any[] {
  console.log('獲取數(shù)據(jù)庫(kù)數(shù)據(jù)')
  var list = [
    {
      title: '222'
    }, {
      title: '333'
    }
  ]
  return list
}

function saveData() {
  console.log('保存')
}

export {
  dbUrl,
  getData,
  saveData
}

// export default getData // export default在一個(gè)模塊中只能用一次节榜,引入時(shí)import getData from ’xxxx/xxx‘

// index.ts

import { getData as get, saveData } from './modules/db'

get()
saveData()

應(yīng)用舉例:封裝db庫(kù)

// modules/db.ts

interface DBI<T> {
 add(info: T):boolean;
 update(info: T, id: number):boolean;
 delete():boolean;
 get(id: number): any[]
}

export 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(): boolean {
   throw new Error("Method not implemented.");
 }
 get(id: number): any[] {
   var list = [
     {
       title: 'xxxx',
       desc: 'xxx1'
     },
     {
       title: 'xxxx',
       desc: 'xxx1'
     },
   ]
   return list
 }
}

// model/user.ts

import { MssqlDb } from '../modules/db'

class UserClass {
 username: string | undefined;
 password: string | undefined;
}

var UserModel = new MssqlDb<UserClass>(); // 用類約束傳入?yún)?shù)的合法性

export {
 UserClass,
 UserModel
}

// index.ts

import { UserClass, UserModel } from './model/user'
import  {ArticleClass, ArticleModel } from './model/article'

var user = new UserClass();
user.username = 'zhangsan'
user.password = '123344'

UserModel.add(user)
var res = UserModel.get(123)
console.log(res)

命名空間 命名空間塊化

namespace A {
  // ...
}

namespace B {
  // ...
  export class Dog {
    name: string;
    constructor(name:string) {
      this.name = name
    }
  }
}

// 調(diào)用命名空間中的方法,或類别智,需要在namespace中暴露export出來(lái)
var d = new B.Dog('jfsldjf')
console.log(d)

可將命名空間當(dāng)作一個(gè)模塊直接暴露出來(lái)

// modules/a.ts
export namespace A {
  // ...
}

// index.ts
import { A } from 'xxxx'
var d = new A.dog('test')

命名空間和模塊的區(qū)別:命名空間主要用于組織代碼宗苍,避免命名沖突;模塊側(cè)重代碼的重用薄榛,一個(gè)模塊可能會(huì)有多個(gè)命名空間

裝飾器

裝飾器:是一種特殊類型的聲明讳窟,能夠被附加到類聲明,方法蛇数,屬性挪钓,或參數(shù)上是越,可以修改類的行為
通俗的講耳舅,裝飾器就是一個(gè)方法,可以注入到類倚评,方法浦徊,屬性參數(shù)上來(lái)擴(kuò)展類,屬性天梧,方法盔性,參數(shù)的功能;

常見(jiàn)裝飾器有:類裝飾器呢岗,屬性裝飾器冕香,方法裝飾器,參數(shù)裝飾器

裝飾器的寫法:普通裝飾器(無(wú)法傳參)后豫;裝飾器工廠(可傳參)

類裝飾器

普通裝飾器(無(wú)法傳參)

// 類裝飾器悉尾,在類聲明之前被聲明(緊接著類聲明),應(yīng)用于類構(gòu)造函數(shù)挫酿,可用來(lái)監(jiān)視构眯、修改、或替換類定義

// 裝飾器
function logClass(params:any) {
  console.log(params) // params 就是當(dāng)前類
  params.prototype.apiUrl = 'xxxx'
  params.prototype.run = function() {
    console.log('run method')
  }
}

@logClass
class HttpClient {
  constructor() {

  }
  getData() {

  }
}

var http: any = new HttpClient()
console.log(http.apiUrl)
http.run()

裝飾器工廠(可傳參數(shù))

// 裝飾器工廠
function logClass(params: string) {
  return function(target: any) { // target為類
    // console.log(target, params)
    target.prototype.apiUrl = params
  }
}

@logClass('http://hello')
class HttpClient {
  constructor() {

  }
  getData() {

  }
}

var http:any = new HttpClient()
console.log(http.apiUrl)

類裝飾器:下面是一個(gè)重載構(gòu)造函數(shù)的例子, (修改當(dāng)前類的構(gòu)造函數(shù)或方法早龟,可看為固定用法)

function logClass(target:any) {
  console.log(target)
  return class extends target {
    apiUrl: any = '修改后數(shù)據(jù)'
    getData() {
      console.log(`${this.apiUrl} + 修改后的`)
    }
  }
}

@logClass
class HttpClient {
  public apiUrl: string | undefined;
  constructor() {
    this.apiUrl = '我是構(gòu)造函數(shù)里面的apiUrl'
  }
  getData() {
    console.log(this.apiUrl)
  }
}

var http = new HttpClient()
http.getData()

屬性裝飾器

// 屬性裝飾器
// 屬性裝飾器表達(dá)式會(huì)在運(yùn)行時(shí)當(dāng)作函數(shù)被調(diào)用惫霸,傳入下列2個(gè)參數(shù)
// 1. 對(duì)靜態(tài)成員來(lái)說(shuō)是類的構(gòu)造函數(shù),對(duì)實(shí)例成員來(lái)說(shuō)是類的原型對(duì)象
// 2. 成員的名字
function logProperty(params:any) {
  return function (target:any, attr: any) {
    console.log(target, attr)
    target[attr] = params
  }
}

@logClass('http://hello')
class HttpClient {
  @logProperty('newUrl')
  public url: any | undefined
  constructor() {

  }
  getData() {
    console.log('getData===>', this.url)
  }
}

var http = new HttpClient()
http.getData()

方法裝飾器

方法裝飾器 會(huì)應(yīng)用到方法的屬性描述符上葱弟,可以用來(lái)監(jiān)視壹店,修改,或者替換方法定義

方法裝飾器會(huì)在運(yùn)行時(shí)芝加,傳入下列三個(gè)參數(shù)

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

方法裝飾器一: 修改當(dāng)前實(shí)例的屬性和方法

function get(params:any) {
  return function(target:any, methodName: any, desc:any) {
    console.log(target, methodName, desc) // 仍可改變類原型上的方法和屬性
    target.apiUrl = 'apiUro'
    target.run = function() {
      console.log('run')
    }
  }
}

class HttpClient {
  public url: any | undefined
  constructor() {

  }
  @get('htttp://dksjflsjkf')
  getData() {
    console.log('getData===>', this.url)
  }
}

var http:any = new HttpClient()
console.log(http.apiUrl)
http.run()

方法裝飾器二: 修改當(dāng)前方法

function get(params:any) {
  return function(target:any, methodName: any, desc:any) {
    console.log(target, methodName, desc.value)

    // 修改裝飾器的方法,把裝飾器方法里面?zhèn)魅氲乃袇?shù)改為string類型
    // 1. 保存當(dāng)前方法
    var oMethod = desc.value;

    desc.value = function(...args: any[]) {
      args = args.map(val => String(val))
      console.log(args)
      // 2. 調(diào)用原來(lái)的舊方法(看是否需要直接覆蓋,可省略)
      oMethod.apply(this, args)
    }
    
  }
}

class HttpClient {
  public url: any | undefined
  constructor() {

  }
  @get('htttp://dksjflsjkf')
  getData(...args:any[]) {
    console.log('我是getData', args)
  }
}

var http:any = new HttpClient()
http.getData(123, 'xdd')

方法參數(shù)裝飾器

參數(shù)裝飾器表達(dá)式會(huì)在運(yùn)行時(shí)當(dāng)作函數(shù)被調(diào)用老赤,可用使用參數(shù)裝飾器為類的原型增加一些元素?cái)?shù)據(jù)轮洋,傳入下列3個(gè)參數(shù)

1. 對(duì)于靜態(tài)成員來(lái)說(shuō)是類的構(gòu)造函數(shù),對(duì)于實(shí)例成員是類的原型對(duì)象
2. 方法的名字
3. 參數(shù)在函數(shù)參數(shù)列表中的索引
function logParam(params: any) {
  return function(target:any, methodName: any, paramsIndex:any) {
    // console.log(params)
    // console.log(target, methodName, paramsIndex)
    target.apiUrl = params
  }
}

class HttpClient {
  public url: any | undefined
  constructor() {

  }
  getData(@logParam('uuid') uuid:any) {
    // console.log(uuid)
  }
}

var http:any = new HttpClient()
console.log(http.apiUrl)
http.getData(123456)

裝飾器的執(zhí)行順序

  1. 屬性 > 方法 > 方法參數(shù) > 類裝飾器
  2. 有多個(gè)同樣的裝飾器抬旺,則會(huì)先執(zhí)行后面的
function logClass1(params:string) {
  return function(target:any) {
    console.log('類裝飾器1')
  }
}

function logClass2(params:string) {
  return function(target:any) {
    console.log('類裝飾器2')
  }
}

function logAttr(params?:string) {
  return function(target:any, attr: any) {
    console.log('屬性裝飾器')
  }
}

function logMethod(params?:string) {
  return function(target:any, methodName: any, desc: any) {
    console.log('方法裝飾器')
  }
}

function logParam1(params?: any) {
  return function(target:any, methodName: any, paramsIndex:any) {
    console.log('方法參數(shù)裝飾器1')
  }
}

function logParam2(params?: any) {
  return function(target:any, methodName: any, paramsIndex:any) {
    console.log('方法參數(shù)裝飾器2')
  }
}

@logClass1('http://1')
@logClass2('http://2')
class HttpClient {
  @logAttr()
  public url: any | undefined
  constructor() {

  }
  @logMethod()
  getData() {
    return true
  }

  setData(@logParam1() attr1:any, @logParam2() attr2: any) {
  }
}

var http:any = new HttpClient()


// 打印結(jié)果是
/ *
    屬性裝飾器
    方法裝飾器
    方法參數(shù)裝飾器2
    方法參數(shù)裝飾器1
    類裝飾器2
    類裝飾器1
*/
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末弊予,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子开财,更是在濱河造成了極大的恐慌汉柒,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件责鳍,死亡現(xiàn)場(chǎng)離奇詭異碾褂,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)历葛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門肢预,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)痹束,“玉大人,你說(shuō)我怎么就攤上這事”韬欤” “怎么了系吭?”我有些...
    開(kāi)封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵啡直,是天一觀的道長(zhǎng)箫柳。 經(jīng)常有香客問(wèn)我,道長(zhǎng)帐姻,這世上最難降的妖魔是什么稠集? 我笑而不...
    開(kāi)封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮饥瓷,結(jié)果婚禮上剥纷,老公的妹妹穿的比我還像新娘。我一直安慰自己扛伍,他們只是感情好筷畦,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著刺洒,像睡著了一般鳖宾。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上逆航,一...
    開(kāi)封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天鼎文,我揣著相機(jī)與錄音,去河邊找鬼因俐。 笑死拇惋,一個(gè)胖子當(dāng)著我的面吹牛周偎,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播撑帖,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼蓉坎,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了胡嘿?” 一聲冷哼從身側(cè)響起蛉艾,我...
    開(kāi)封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎衷敌,沒(méi)想到半個(gè)月后勿侯,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡缴罗,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年助琐,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片面氓。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡兵钮,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出侧但,到底是詐尸還是另有隱情矢空,我是刑警寧澤,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布禀横,位于F島的核電站,受9級(jí)特大地震影響粥血,放射性物質(zhì)發(fā)生泄漏柏锄。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一复亏、第九天 我趴在偏房一處隱蔽的房頂上張望趾娃。 院中可真熱鬧,春花似錦缔御、人聲如沸抬闷。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)笤成。三九已至,卻和暖如春眷茁,著一層夾襖步出監(jiān)牢的瞬間炕泳,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工上祈, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留培遵,地道東北人浙芙。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像籽腕,于是被迫代替她去往敵國(guó)和親嗡呼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

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