Ts – 大地老師視頻筆記
Ts數據類型
typescript中爲了使編寫的代碼更規範,更有利於維護,增加了類型校驗,寫Ts代碼必須指定類型
布爾類型
var flag:boolean = true
// flag = 123 錯誤寫法
flag = false
console.log(flag);//false
數字類型
/**數字類型number */
let num:Number = 123
num = 456
console.log(num);
字符串類型
/**string類型 */
let str:String = 'sssss'
console.log(str);
數組類型
/**數組類型 */
//1.第一種定義數組的方式
let arr:Number[] = [11,12,13,14]//數組中的所有元素都是number類型
console.log(arr);
//2.第二種定義數組的方式
let arr1:Array<Number> = [11,12,13,14,15]//數組中的所有元素都是number類型
console.log(arr1);
//3.第三種定義數組的類型
let arr2:any[] = [11,12,13,'333',false]
元組類型
/**元組類型---屬於數組的一種 */
let arr2:[number, string,number,boolean] = [123,'234',222,false]
console.log(arr2);
枚舉類型
隨着計算機的不斷普及,程序不僅只用於數值計算,還更廣泛的用於處理非數值數據。例如:性別、月份、星期幾、顏色、單位名稱、簡歷、職業等,都不是數值數據,在其他程序設計語言中,一般用一個數值來代表某一狀態,這種處理方法不直觀,閱讀性差,如果能在程序中用自然語言中有相應含義的單詞來代表某一狀態,則程序就很容易閱讀和理解,也就是說,實現考慮到某一變量可能的取值,儘量用自然語言中涵義清楚地單詞來表示他的每一個值,這種方法稱爲枚舉法,用這種方法定義的類型爲枚舉類型
/**枚舉類型 */
/**
* enum 枚舉名 {
* 標識符[=整型常數]
* 標識符[=整型常數]
* 標識符[=整型常數]
* ...
* 標識符[=整型常數]
* }
*/
enum Flag {success=1, flase=2,pending}
let f:Flag = Flag.success
let f1:Flag = Flag.pending
console.log(f);//1
console.log(f1);//3
enum Color {blue, 'yellow', white}
let c:Color = Color.yellow
//如果標識符沒有賦值,那麼它的值就是下標
console.log(c);//1
任意類型(any)
/**任意類型(any) */
//1.基本使用
let n:any = 111
n = 'str'
n = true
console.log(n);
//2.用處:不加any會報錯
let obx:any = document.getElementById('id')
obx.style.color = 'red'
null和undefined — 其他數據類型(never類型)的子類型
/**null和undedined */
//let n1:number
//console.log(n1);//可以瀏覽器輸出,但Ts報錯
let n3:number | undefined
n3 = 12311
console.log(n3); //12311
//定義未賦值
let n4:number | undefined
console.log(n4); //undefined
let n5:null | number | undefined
n5 = 3333
console.log(n5);
void類型:Ts中的void表示沒有任何類型,一般用於定義方法的時候方法沒有返回值
/**void類型 */
//es5定義方法
function run () {
console.log('run');
}
run()
//void定義方法:沒有返回值
function run1():void {
console.log('run1');
}
run1()
//如果方法有返回值,返回值什麼類型就給方法指定什麼類型
function number():number {
return 1
}
console.log(number());
never類型:代表從不會出現的值,這意味着聲明never的變量只能被never類型所賦值
/**never類型 --- 一般不用 */
let a:undefined
//a = 123 //報錯
a = undefined //正確
let b:null
//b = 222 //報錯
b = null //正確
let d:never
//d = 123 //報錯
a = (() => { //正確
throw new Error('報錯')
})()
函數
/**函數 */
/**3.1 ES5定義函數兩種方法 */
1.函數聲明法
function run () {
return 'run'
}
//2.匿名函數
let run2 = function () {
return 'run2'
}
/**3.2 ts中函數定義方法 */
1.函數聲明法
function run():string {
//return 123 //錯誤寫法
return 'run'
}
//匿名函數寫法
let run2 = function ():number {
return 123
}
alert(run2())
/**3.3 ts中定義方法傳參 */
function getInfo (name:string, age:number):string {
return `${name} --- ${age}`
}
console.log(getInfo('111',23));
let get1 = function (name:string, age:number):string {
return `${name} --- ${age}`
}
console.log(get1('www',45));
/**3.4 Ts方法的可選參數
* 可選參數必須配置到參數最後面
*/
//1.ES5裏面的實參和形參可以不一樣,但Ts中必須一樣,如果不一樣,就需要配置可選參數
function getInfo (name:string, age?:number):string {//age加個?表示可選參數
if (age) {
return `${name} --- ${age}`
} else {
return `${name} --- 年齡保密`
}
}
console.log(getInfo('111'));
/**3.5 Ts方法的默認參數
* ES5沒有辦法設置默認參數,ES6和Ts中都可以設置默認參數
*/
function getInfo (name:string, age:number=20):string {//age加個?表示可選參數
if (age) {
return `${name} --- ${age}`
} else {
return `${name} --- 年齡保密`
}
}
console.log(getInfo('111',40));
/**
* 3.6 剩餘參數--三點運算符
*/
//1.三點運算符,接受形參傳過來的值
function sum (a:number, ...result:number[]):number {
let sum = 0
for(let i=0; i<result.length; i++) {
sum += result[i]
}
return sum
}
console.log(sum(1,2,3,4,5));//14,把1賦值給了a
/**3.7 ts函數的重載
* 1. java中的方法的重載:重載指的是兩個或兩個以上的同名函數,但他們的參數不一樣,這時會出現函數重載的情況
* 2. Ts的重載:通過爲同一個函數提供多個函數類型定義,ts爲了兼容es5和es6,所以重載的寫法與java中有區別
*/
//ES5出現同名方法,下面的會替換上面的
// function css (config) {}
// function css (config, value) {}
//ts中的重載(1)
function getInfo (name:string):string;
function getInfo (age:number):number;
function getInfo (str:any):any {
if (typeof str === 'string') {
return '我叫' + str
} else {
return '年齡' + str
}
}
console.log(getInfo('zhangsan'));//正確
console.log(getInfo(20)); //正確
console.log(getInfo(true)); //報錯,錯誤寫法
//ts中的重載(2)
function getInfo (name:string):string;
function getInfo (name:string, age:number):string;
function getInfo (name:any, age?:any):any {
if (age) {
return '我叫' + name + ',今年' + age
} else {
return '我叫' + name
}
}
console.log(getInfo('wwwq',30));//正確
console.log(getInfo(222)); //錯誤
/**3.8 箭頭函數 es6
* this指向問題,箭頭函數裏面的this指向上下文
*/
ES5中的類和靜態方法以及繼承
/**ES5裏面的類 */
/** 1.對象冒充實現繼承 */
function Person () {
this.name = 'ww'
this.age = 30
this.run = function () {} //實例方法
}
Person.getInfo = function () {} //靜態方法
Person.prototype.work = function () {} //
Person.getInfo() //調用靜態方法
const p = new Person()
console.log(p.name);
//web類繼承Person類 原型鏈+對象冒充的組合繼承模式
function Web () {
Person.call(this) //對象冒充實現繼承
}
let w = new Web()
w.run() //調用Person的run方法,對象冒充可以繼承構造函數裏面的屬性和方法
w.work() //報錯,對象冒充沒法繼承原型鏈上的屬性和方法
/** 2.原型鏈實現繼承
* 問題:實例化子類的時候沒法給父類傳參
*/
function Person () {
this.name = 'ww'
this.age = 30
this.run = function () {} //實例方法
}
Person.getInfo = function () {} //靜態方法
Person.prototype.work = function () {} //
Person.getInfo() //調用靜態方法
const p = new Person()
console.log(p.name);
function Web () {}
Web.prototype = new Person() //原型鏈實現繼承,即可以繼承構造函數中的屬性和方法,也可以繼承原型鏈上的屬性和方法
let w = new Web()
w.run()//正確
w.work() //正確
/** 3.原型鏈+構造函數的組合繼承模式 */
function Person (name, age) {
this.name = name
this.age = age
this.run = function () {
alert(this.name + '喫飯')
} //實例方法
}
Person.getInfo = function () {} //靜態方法
Person.prototype.work = function () {} //
Person.getInfo() //調用靜態方法
const p = new Person()
console.log(p.name);
function Web (name, age) {
Person.call(this, name, age) //對象冒充實現繼承,實例化子類可以給父類傳參
}
Web.prototype = new Person() //或者可以寫爲:Web.prototype = Person.prototype
let w = new Web('333',34) //實例化子類可以給父類傳參
ES6中的類
/** es6中定義類 */
class Person {
//定義屬性,前面省略了public關鍵詞
name:string
constructor (name:string) { //構造函數,實例化類的時候觸發的方法
this.name = name
}
run():void {
alert(this.name)
}
}
let p = new Person('張三')
p.run()
ts中的類
/**ts中定義類 */
class Person {
//定義屬性,前面省略了public關鍵詞
name:string
constructor (name:string) { //構造函數,實例化類的時候觸發的方法
this.name = name
}
getName():string {
return this.name
}
setName(name:string):void {
this.name = name
}
}
let p = new Person('張三')
console.log(p.getName());
p.setName('李四')
console.log(p.getName());
/** 1.ts中實現繼承 -- extends super*/
class Person {
name:string
constructor (name:string) {
this.name = name
}
run():string {
return `${this.name}在運動`
}
}
class Web extends Person {
constructor (name:string) {
super(name)/**初始化父類構造函數 */
}
}
let w = new Web('網五')
console.log(w.run());
/** 2.ts中繼承的探討
* 父類的方法和子類的方法一致 -- 先在子類中找
* */
class Person {
name:string
constructor (name:string) {
this.name = name
}
run():string {
return `${this.name}在運動`
}
work():string {
return `${this.name}在工作`
}
}
class Web extends Person {
constructor (name:string) {
super(name)/**初始化父類構造函數 */
}
work():string {
return `${this.name}在在在工作111`
}
}
let w = new Web('網五')
console.log(w.run());
console.log(w.work());
/** 3.類裏面的修飾符
* ts裏面定義屬性時,給我們提供了三種修飾符
* public -- 公有的,在當前類裏面,子類,類外面都可以訪問
* private -- 私有的,在當前類裏面可以訪問,子類和類外部無法訪問
* protected -- 保護類型 在當前類裏面和子類裏面可以訪問,類外部無法訪問
* 屬性如果不加修飾符,默認是公有的
*/
/** 4.靜態屬性,靜態方法 */
class Person {
name:string
static age:number = 20 //靜態屬性
constructor (name:string) {
this.name = name
}
run () { //實例方法
alert(`${this.name}在運動`)
}
work () { //實例方法
alert(`${this.name}在工作`)
}
static Print () { //靜態方法,在靜態方法中沒法調用類裏面的屬性,但可以調用靜態屬性
console.log('qqq');
console.log(Person.age + 'www');
}
}
let p = new Person('張三')
Person.Print() //調用靜態方法
console.log(Person.age); //調用靜態屬性
/** 5.多態:父類定義一個方法不實現,讓繼承他的子類去實現,每一個子類有不同表現
* 多態屬於繼承
*/
class Animal {
name:string
constructor (name:string) {
this.name = name
}
eat () {
console.log('喫的方法');
}
}
class Dog extends Animal {
constructor (name:string) {
super(name)
}
eat () {
return `${this.name}喫肉`
}
}
class Cat extends Animal {
constructor (name:string) {
super(name)
}
eat () {
return `${this.name}恥笑沒`
}
}
/**6.抽象方法
* ts中的抽象類:是提供其他類繼承的基類,不能直接被實例化
* 用abstract關鍵字定義抽象類和抽象方法,抽象類中的抽象方不包含具體實現並且必須在派生類中實現
* abstract抽象方法只能放在抽象類中
*/
abstract class Animal {
name:string
constructor (name:string) {
this.name = name
}
abstract eat():any
}
class Dog extends Animal {
constructor (name:string) {
super(name)
}
//抽象類的子類必須實現抽象類裏面的抽象方法
eat () {
console.log(`${this.name}喫糧食`);
}
}
let dog = new Dog('小狗')
dog.eat()
接口
- 接口作用:在面向對象的編程中,接口是一種規範的定義,它定義了行爲和動作的規範,在程序設計裏面,接口起到一種限制和規範的作用,接口定義了一批類所需要遵守的規範,接口不關心這些類的內部狀態數據,也不關心這些類裏面方法的實現細節,他只規定這些類裏必須提供某些方法,提供這些方法的類就可以滿足實際需要
- interface定義接口
- 屬性類型接口
/**屬性接口 -- 對json的約束 */
//ts中自定義方法傳入參數時對json進行約束
function printLabel (labelInfo:{label:string}):void {
console.log('printLabel');
}
printLabel({label : '張三'}) //正確寫法
//printLabel({name : 'ddd'}) //報錯,傳入的對象必須有label
//對批量方法傳入參數進行約束
interface FullName { //傳入對象的約束,屬性接口
firstName:string
secondName:string
}
function printName (name:FullName) {
//要求 -- 必須傳入對象,對象中必須要有firstName和secondName
console.log(name.firstName + '--' + name.secondName);
}
function printInfo (name:FullName) {
console.log('--' + name.firstName + '--' + name.secondName + '--');
}
//printName(123) //報錯
const obj = { //傳入的參數必須包含firstName和secondName
age : 20,
firstName : 'z',
secondName : '3'
}
printName(obj)
printInfo(obj)
/**接口:可選屬性 */
interface FullName1 {
firstName:string
secondName?:string //加?表示該參數爲可選參數
}
function getName (name:FullName1) {
console.log(name.firstName + '...' + name.secondName);
}
getName({
firstName : '111'
})
getName({
firstName : 'aaa',
secondName : 'eee'
})
- 小案例
/**例子 */
interface Config {
type : string
url : string
data? : string
dataType : string
}
function ajax (config:Config) {
var xhr = new XMLHttpRequest()
xhr.open(config.type , config.url, true)
xhr.send(config.data)
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
console.log('success');
if (config.dataType == 'json') {
JSON.parse(xhr.responseText)
} else {
console.log(xhr.responseText);
}
}
}
}
ajax({
type : 'get',
url : 'http://www.baidu.com',
dataType : 'json',
data : 'name=123'
})
- 函數類型接口 – 對方法傳入的參數以及返回值進行約束,批量約束
/**函數類型接口 -- 對方法傳入的參數以及返回值進行約束 */
//加密的函數類型接口
interface encrypt {
(key:string, value:string):string
}
let md5:encrypt = function (key:string, value:string):string {//必須滿足接口約束
return (key + value)
}
console.log(md5('z','s'));
- 可索引接口
- 對數組的約束
/**可索引接口 -- 對數組的約束 */
interface UserArr {
[index:number]:string
}
let ar1:UserArr = ['aaa', 'bbb']
console.log(ar1[0]);
- 對對象的約束
interface UserObj {
[index:string]:string
}
let obj:UserObj = {
name : '20',
age : '20'
}
- 類類型接口
interface Animal1 {
name:string
eat1(str:string):void
}
class Dog1 implements Animal1 {
name:string
constructor (name:string) {
this.name = name
}
eat1 () {
console.log(this.name + '喫糧食');
}
}
const dog1 = new Dog1('小黑')
dog1.eat1()
class Cat1 implements Animal1 {
name:string;
constructor (name:string) {
this.name = name
}
eat1 (food:string) {
console.log(this.name + '喫' + food);
}
}
let ca = new Cat1('小花')
ca.eat1('老鼠')
- 接口的擴展 – 接口繼承接口
/** 接口的擴展 -- 接口可以繼承接口 */
interface Animal2 {
eat ():void
}
interface Person extends Animal2 {
work ():void
}
class Program {
public name:string
constructor (name:string) {
this.name = name
}
coding (coding:string) {
console.log(this.name + coding);
}
}
class Man extends Program implements Person {
constructor (name:string) {
super(name)
}
eat () {
console.log(this.name + '在喫飯');
}
work () {
console.log(this.name + '在寫代碼');
}
}
let m = new Man('小李')
m.eat() //小李在喫飯
m.work() //小李在寫代碼
m.coding('java')//小李Java
泛型
- 泛型:軟件工程中,我們不僅要創建一致的定義良好的API,同時也要考慮可重用性,組件不僅能夠支持當前的數據類型,同時也能支持未來的數據類型,這在創建大型系統時爲你提供了十分靈活的功能
- 在像C#和Java這樣的語言中,可以使用泛型來創建可重用的組件,一個組件可以支持多種類型的數據,這樣用戶就可以以自己的數據類型來使用組件
- 通俗的來說:泛型就是解決類、接口、方法的複用性、以及對不特定數據類型的支持
- 泛型的定義和泛型的函數
/** 泛型:可以支持不特定的數據類型 要求:傳入的參數和返回的參數一致 */
// T表示泛型,具體什麼類型是調用這個方法的時候決定的
function getDate<T>(value:T):T {
return value
}
console.log(getDate<number>(123));
console.log(getDate<string>('222'));
- 泛型類
/** 泛型類:比如有個最小堆算法,需要同時支持返回數字和字符串兩種類型,通過類的泛型來實現*/
class MinClass<T> {
public list:T[] = []
add (num:T):void {
this.list.push(num)
}
min ():T {
let minNum = this.list[0]
for (let i=0; i<this.list.length; i++) {
if (minNum > this.list[i]) {
minNum = this.list[i]
}
}
return minNum
}
}
let m1 = new MinClass<number>() //實例化類,並且指定類的類型是number
m1.add(2)
m1.add(44)
m1.add(3)
m1.add(5)
m1.add(12)
console.log(m1.min())
let m2 = new MinClass<string>()//實例化類,並且指定類的類型是string
m2.add('12')
m2.add('13')
m2.add('14')
console.log(m2.min());
- 泛型類接口
//第一種定義泛型接口的方法
interface ConfigFn {
<T>(value:T):T
}
const setDate:ConfigFn = function <T>(value:T):T {
return (value)
}
setDate<string>('123')
setDate<number>(1222)
//第二種定義泛型接口的方法
interface ConfigFn<T> {
(value:T):T
}
function getDate<T>(value:T):T {
return (value)
}
let myGetDate:ConfigFn<string> = getDate
myGetDate('123')
- 把類作爲參數來約束數據傳入類型
/**
* 定義一個User類,這個類的作用就是映射數據庫字段,
* 然後再定義一個MsqlDb的類,這個類用於操作數據庫,
* 然後把User類作爲參數傳入到MsqlDb
*/
/*普通寫法*/
class User {
username:string | undefined; //不加undefined會報錯
password:string | undefined
}
class MySqlDb {
add (user:User):boolean {
console.log(user);
console.log(user.username);
return true
}
}
let u = new User()
u.username = '張三'
u.password = '122'
let my = new MySqlDb()
my.add(u)
/**泛型寫法*/
class User {
username:string | undefined; //不加undefined會報錯
password:string | undefined
}
//操作數據庫對額泛型類
class MySqlDb<T> {
add (user:T):boolean {
console.log(user);
return true
}
}
let u = new User()
u.username = '張三'
u.password = '1223'
//User類當作參數傳入泛型類中
let my = new MySqlDb<User>()
my.add(u)
//my.add('1223')//報錯
/*第三種寫法*/
class User {
username:string | undefined; //不加undefined會報錯
password:string | undefined
constructor (params:{
username:string | undefined
password:string | undefined
}) {
this.username = params.username
this.password = params.password
}
}
class MySqlDb<T> {
add (user:T):boolean {
console.log(user);
return true
}
}
let u = new User({
username : '張三',
password : '12312'
})
//User類當作參數傳入泛型類中
let my = new MySqlDb<User>()
my.add(u)
- 小案例
/**
* 功能:定義一個操作數據庫的庫,支持MySQL,Mssql, MongoDb
* 要求:MySQL,Mssql, MongoDb功能一樣,都有add, delete, update, get方法
* 注意:約束統一的規範以及代碼重用
* 解決方案:需要約束規範所以要定義接口,需要代碼重用,所以要用到泛型
*
*/
interface DBI<T> {
add (info:T):boolean;
update (info:T, id:number):boolean;
delete (id:number):boolean;
get (id:number):any[] // 返回任意類型的數組
}
//定義一個操作MySQL數據庫的類
// 要實現泛型接口,這個類也應該是泛型類
class MySqlDb<T> implements DBI<T> {
constructor () {
console.log('建立數據庫鏈接');
}
add(info: T): boolean {
console.log(info);
return true
}
update(info: T, id: number): boolean {
throw new Error("Method not implemented.");
}
delete(id: number): boolean {
throw new Error("Method not implemented.");
}
get(id: number): any[] {
let list = [
{
title: 'xxxx',
dec: 'xxxxxxxx'
},
{
title: 'xxxx',
dec: 'xxxxxxx'
}
]
return list
}
}
class MssqlDb<T> implements DBI<T> {
add(info: T): boolean {
console.log(info);
return true
}
update(info: T, id: number): boolean {
throw new Error("Method not implemented.");
}
delete(id: number): boolean {
throw new Error("Method not implemented.");
}
get(id: number): any[] {
let list = [
{
title: 'xxxx',
dec: 'xxxxxxxx'
},
{
title: 'xxxx',
dec: 'xxxxxxx'
}
]
return list
}
}
// 操作用戶表 定義一個user類和數據表映射
class User {
username: string | undefined
password: string | undefined
}
let u = new User()
u.username = '張三'
u.password = '2222'
let omysql = new MySqlDb<User>()
let omssql = new MssqlDb<User>()
//omysql.add(u)
omssql.add(u)
// 獲取ID=4的數據
let data = omssql.get(4)
console.log(data);
模塊
內部模塊
- 又稱命名空間
- 在代碼量較大的情況下,爲了避免各種變量名相沖突,可將相似功能的函數類,接口等放置到命名空間內
- 同Java包、.net的命名空間一樣,Ts的命名空間可以將代碼包裹起來,之對外暴露需要在外部訪問的對象,命名空間內的對象通過export導出
外部模塊 – 簡稱模塊
命名空間和模塊的區別
- 命名空間:內部模塊,主要用於組織代碼,避免命名衝突
- 模塊: ts外部模塊的簡稱,側重代碼的複用,一個模塊裏可能有多個命名空間
裝飾器
- 裝飾器是一種特殊類型的聲明,它能夠被附加到類聲明,方法,屬性或參數上,可以修改類的行爲
- 通俗的講,裝飾器就是一個方法,可以注入到類,方法,屬性參數上擴展類,屬性,方法,參數的功能
- 常見的裝飾器有:類裝飾器、屬性裝飾器、方法裝飾器、參數裝飾器
- 裝飾器的寫法:普通裝飾器(無法傳參),裝飾器工廠(可傳參)
- 裝飾器是過去幾年中js的最大成就之一,已經是ES7標準特性之一
類裝飾器
- 類裝飾器再類聲明之前被聲明(僅靠着類聲明),類裝飾器應用於類構造函數。可以用來監視,修改、替換類定義
- 普通裝飾器(無法傳參數)寫法
//類裝飾器
function logClass (params:any) {
console.log(params);
// params就是當前類
params.prototype.apiUrl = 'xxxxx' //動態擴展的屬性
params.prototype.run = function () {
console.log('我是run方法');
}
}
@logClass
class HttpClient {
constructor () {
}
getData() {
}
}
let client:any = new HttpClient()
console.log(client.apiUrl);
console.log(client.run());
- 裝飾器工廠寫法
//裝飾器工廠
function logClass (params:string) {
return function (target:any) {
console.log(target); // 當前的類
console.log(params); // 傳入的參數:hello
target.prototype.ap = 'wwwww'
}
}
@logClass('hello')
class HttpClient {
constructor () {
}
getdata () {
}
}
let ccc:any = new HttpClient()
console.log(ccc.ap);
- 小案例
/**
* 重載構造函數的例子
* 類裝飾器表達式會在運行時當作函數被調用,類的構造函數作爲其唯一參數
* 如果類裝飾器返回一個值,他會使用提供的構造函數來替換類的聲明
*/
function logClass (params:any) {
console.log(params); // 當前類
return class extends params {
apUrl:any = '我是修改後的URL'
getData () {
console.log(this.apUrl + '----');
}
}
}
@logClass
class HttpClient {
public apUrl:string | undefined
constructor () {
this.apUrl = 'wwweee'
}
getData () {
console.log(this.apUrl);
}
}
let http = new HttpClient()
http.getData()
屬性裝飾器
- 屬性裝飾器表達式會在運行時當作函數被調用,傳入下列兩個參數
- 對於靜態成員來說是類的構造函數,對於實例成員是類的原型對象
- 成員名字
/**屬性裝飾器 */
function logProperty (params:any) {
return function (target:any, attr:any) {
console.log('attr:' + attr);
console.log('屬性target:' + target);
target[attr] = params
}
}
//類裝飾器
function logClass (params:any) {
return function (target:any) {
console.log('類target:' + target);
console.log('params:' + params);
}
}
@logClass('xxxx')
class HttpClient {
@logProperty('xxxx222')
public url:string | undefined
constructor () {
}
getData () {
console.log('url:' + this.url);
}
}
let htt = new HttpClient()
htt.getData() // xxxx222
方法裝飾器
- 它會被應用到方法的 屬性描述符上,可以用來監視,修改或者替換方法定義
- 傳入一下參數:
- 對於靜態成員來說是類的構造函數,對於實例成員是類的原型對象
- 成員的名字
- 成員的屬性描述符
/**方法裝飾器 */
function lgMessage (params:any) {
return function (target:any, methodsName:any, desc:any) {
console.log(target);
console.log(methodsName);
console.log(desc.value); // 當前的方法
// target.apiUrl = 'llllg'
// target.run = function () {
// console.log('我是run');
// }
/**修改裝飾器的方法 -- 把裝飾器裏面傳入的所有參數改爲string類型 */
// 1.保存當前的方法
let oMethods = desc.value
// 2.修改方法
desc.value = function (...args:any[]) { //使用三點運算符接收參數
args = args.map((value) => {
return String(value)
})
console.log(args);
oMethods.apply(this, args)
}
}
}
class HttpClient {
public url:string | undefined
constructor () {
}
@lgMessage('methods')
getData (...args:any) {
console.log(args);//["1222", "3333"]
console.log('我是getData裏面的方法');
}
}
let h:any = new HttpClient()
// h.run()
// console.log(h.apiUrl);
h.getData('1222','3333') //["1222", "3333"] 我是getData裏面的方法
方法參數裝飾器
- 參數裝飾器表達式會在運行時當作函數被調用,可以使用參數裝飾器爲類的原型增加一些元素數據
- 參數如下:
- 對於靜態成員來說是類的構造函數,對於實例成員是類的原型對象
- 方法的名字
- 參數在函數參數列表中的索引
/***參數裝飾器 */
function logParams (params:any) {
return function (target:any, methodsName:any, paramsIndex:any) {
console.log(params); //uuid
console.log(target);
console.log(methodsName);
console.log(paramsIndex);
target.apiUrl = params
}
}
class HttpClient {
public url:string | undefined
constructor () {
}
getData (@logParams('uuid') uuid:any) {
console.log(uuid); // 12345
}
}
let h:any = new HttpClient()
h.getData(12345)
console.log(h.apiUrl); //uuid
裝飾器的執行順序
- 屬性 > 方法 > 方法參數 > 類
- 如果有多個同樣的裝飾器,會先執行後面的