裝飾器
- 裝飾器是一種特殊的類型聲明,它可以被附加到類聲明、方法、屬性、參數上,能夠修改類的行爲;
- 通俗來說裝飾器就是一個方法,能夠 被注入到類、方法、屬性、參數上來擴展類、方法、屬性、參數的功能;
- 常見裝飾器有:類裝飾器、方法裝飾器、屬性裝飾器、參數裝飾器;
- 裝飾器寫法:普通裝飾器(沒法傳參)、裝飾器工廠(可傳參)
- 裝飾器是過去幾年最大成就之一,已經是es7標準特性之一;
類裝飾器
- 類裝飾器在類聲明以前被聲明,(緊靠着類聲明),類裝飾器應用於類構造函數,能夠用來監視、修改或替換類定義;
// 類裝飾器:普通裝飾器(沒法傳參)
function logClass(params){
// params 就是當前類
console.log(params)
params.prototype.apiUrl = "動態擴展的屬性"
params.prototype.fetch = function(){
console.log('我是一個fetch方法')
}
}
@logClass
class HttpClient {
constructor(){
}
getData(){
}
}
let http = new HttpClient()
console.log(http.apiUrl) // 動態擴展的屬性
http.fetch() // 我是一個fetch方法
// 類裝飾器:裝飾器工廠(能夠傳參)
function logClass(params){
console.log(params)
// params調用時的實參
return function(target){
// target 當前類 HttpClient
console.log(target)
params.prototype.apiUrl = params
}
}
@logClass('newbanker')
class HttpClient {
constructor(){
}
getData(){
}
}
let http = new HttpClient()
console.log(http.apiUrl) // newbanker
// 裝飾器能夠修改當前類的構造函數和方法
// 類裝飾器表達式會在運行時當作函數被調用,類的構造函數做爲其惟一參數
// 若是類裝飾器返回一個值,它會使用提供的構造函數來替換類的聲明
// 下面是一個函數重載的例子
function logClass(params){
console.log(params)
// params調用時的實參
return class extends target {
apiUrl = "我是修改後的數據"
getData(){
console.log(this.apiUrl+'------')
}
}
}
@logClass
class HttpClient {
constructor(){
this.apiUrl = "我是構造函數裏面的apiUrl"
}
裝飾器
- 裝飾器是一種特殊的類型聲明,它可以被附加到類聲明、方法、屬性、參數上,能夠修改類的行爲;
- 通俗來說裝飾器就是一個方法,能夠 被注入到類、方法、屬性、參數上來擴展類、方法、屬性、參數的功能;
- 常見裝飾器有:類裝飾器、方法裝飾器、屬性裝飾器、參數裝飾器;
- 裝飾器寫法:普通裝飾器(沒法傳參)、裝飾器工廠(可傳參)
- 裝飾器是過去幾年最大成就之一,已經是es7標準特性之一;
類裝飾器
- 類裝飾器在類聲明以前被聲明,(緊靠着類聲明),類裝飾器應用於類構造函數,能夠用來監視、修改或替換類定義;
// 類裝飾器:普通裝飾器(沒法傳參)
function logClass(params){
// params 就是當前類
console.log(params)
params.prototype.apiUrl = "動態擴展的屬性"
params.prototype.fetch = function(){
console.log('我是一個fetch方法')
}
}
@logClass
class HttpClient {
constructor(){
}
getData(){
}
}
let http = new HttpClient()
console.log(http.apiUrl) // 動態擴展的屬性
http.fetch() // 我是一個fetch方法
// 類裝飾器:裝飾器工廠(能夠傳參)
function logClass(params){
console.log(params)
// params調用時的實參
return function(target){
// target 當前類 HttpClient
console.log(target)
params.prototype.apiUrl = params
}
}
@logClass('newbanker')
class HttpClient {
constructor(){
}
getData(){
}
}
let http = new HttpClient()
console.log(http.apiUrl) // newbanker
// 裝飾器能夠修改當前類的構造函數和方法
// 類裝飾器表達式會在運行時當作函數被調用,類的構造函數做爲其惟一參數
// 若是類裝飾器返回一個值,它會使用提供的構造函數來替換類的聲明
// 下面是一個函數重載的例子
function logClass(params){
console.log(params)
// params調用時的實參
return class extends target {
apiUrl = "我是修改後的數據"
getData(){
console.log(this.apiUrl+'------')
}
}
}
@logClass
class HttpClient {
constructor(){
this.apiUrl = "我是構造函數裏面的apiUrl"
}
getData(){
console.log(this.apiUrl)
}
}
let http = new HttpClient()
console.log(http.apiUrl) // 我是修改後的數據
屬性裝飾器
- 屬性裝飾器會在運行時當作函數被調用,傳入下列兩個參數:
- 對應靜態成員來講是類的構造函數,對於實例成員是類的原型對象;
- 屬性成員的名稱;
// 類裝飾器:裝飾器工廠(能夠傳參)
function logClass(params){
console.log(params)
// params調用時的實參
return function(target){
// target 當前類 HttpClient
console.log(target)
}
}
// 屬性裝飾器
function logProperty(params){
return function(target, attr){
console.log(target) //
console.log(attr) // 當前屬性url
target.attr = params
}
}
@logClass
class HttpClient {
@logProperty('https://baidu.com')
public url
getData(){
}
}
方法裝飾器
- 方法裝飾器會被用到方法的屬性描述符上,能夠用來監視、修改或者替換方法定義;
- 方法裝飾器會在運行時傳入如下3個參數:
- 對於靜態成員來講是類的構造函數,對於實例來講是類的原型對象;
- 成員的名字
- 成員的屬性描述符
// 方法裝飾器
function logMethod(params){
return function(target, methodName, desc){
console.log(target) // 原型對象,能夠擴展類的原型屬性和方法;
// 能夠擴展當前實例的屬性和方法
target.apiUrl = "http://www.sina.cn"
target.run = function(){
console.log('run')
}
console.log(methodName) // 當前方法名 getData
// 修改裝飾器的方法,把裝飾器方法裏面傳入的全部參數改成string類型;
// 保存當前方法
let save = desc.value
desc.value = function(...args){
args.map((v) => {
return String(v)
})
console.log(v)
}
console.log(desc) // 描述信息 { value: f, xxx: xxx }
// 不加此方法會直接替換實例的方法,加上會修改
save.apply(this, args) // 把當前方法this傳進去,表明在這個方法裏面調用save方法;並傳入參數;
}
}
class HttpClient {
public url: any | undefind;
constructor(){
}
@get('http://www.baidu.com')
getData(args){
console.log(args) // ['123', 'string']
console.log('我是getData的method')
}
}
let http = new HttpClient();
console.log(http.apiUrl) // http://www.sina.cn
http.getData(123, 'string')
方法參數裝飾器
- 參數裝飾器表達式會在運行時當作函數被調用,能夠使用參數裝飾器爲類的原型增長一些元素數據,傳入下列三個參數;
- 對應靜態成員來講是類的構造函數,對應實例成員是類的原型對象
- 參數的名字
- 參數在函數參數列表中的索引
// 方法參數裝飾器
function logParams(params){
return function(target, paramsName, paramsIndex){
console.log(params) // xxxx
console.log(target) //
console.log(paramsName) // getData
console.log(paramsIndex) // 0
}
}
class HttpClient {
getData(@logParams1('xxxx') uuid: any, @logParams2('xxxx') name: any){
console.log(uuid) // 123
}
}
let http: any = new HttpClient();
http.getData(123)
裝飾器執行順序
- 屬性 》 方法 》 方法參數 》 類
- 統一類型的裝飾器,若是有多個,從後往前、從下往上執行
@logClass1('http:www.baidu.con')
@logClass2('xxxx')
class HttpClient {
@logAttribute()
public apiUrl: string | undefind
constructor(){
}
@logMethod()
getData(){
}
setData(@logParams1() attr1: any, @logParams2() attr2: any){
}
}
let http: any = new HttpClient();
// 屬性裝飾器 > 方法裝飾器 > 方法參數裝飾器2 > 方法參數裝飾器1 > 類裝飾器2 > 類裝飾器1