tsconfig.json中开启对应配置从而让ts支持装饰器
"experimentalDecorators": true,
装饰器是一种特殊类型声明, 它能够被附加到类声明、方法、属性或者参数上, 可以修改类的行为,
通俗的讲装饰器就是一个方法,可以注入到类,方法,属性参数上来扩展类,属性,方法,参数功能
装饰器求值后必须为一个函数,它会在运行时被调用,被装饰的声明信息做为参数传入
常见的装饰器:属性装饰器,方法装饰器,参数装饰器
普通修饰器(无法传参)、装饰器工厂(可以传参)
tsfunction nameClass(params:any){
console.log("装饰器",params)
}
@nameClass class people {
constructor(){
}
}
tsfunction nameClass(params:any){
return (target:any)=>{
console.log("装饰器",params,target)
}
}
@nameClass(2) class people {
constructor(){
}
}
由上至下依次对装饰器表达式求值
求值的结果会被当作函数,由下至上依次调用
tsfunction nameClass(params:any){
console.log("装饰器1")
return (target:any)=>{
console.log("装饰器1",params,target)
}
}
function ageClass(params:any){
console.log("装饰器2")
return (target:any)=>{
console.log("装饰器2",params,target)
}
}
@nameClass(1) @ageClass(2) class people {
constructor(){
}
}
ts装饰器1
装饰器2
装饰器2 2 class people {
constructor() {
}
}
装饰器1 1 class people {
constructor() {
}
}
装饰器求值(即工厂函数) 类中不同声明上的装饰器将按以下顺序应用:
应用于类构造函数,其参数是类的构造函数
ts// 类装饰器
function addName(constructor:new() => any){
constructor.prototype.name = "xm"
}
@addName
class ClassD {}
//使用接口,声明一个的类名相同的接口,声明合并;不然报错ClassD上没有name
interface ClassD{
name:string
}
const d = new ClassD()
console.log(d.name) //xm
tsfunction classDecorator<T extends new(...args:any[])=>{}>(target:T) {
return class extends target {
public newProperety = "new property"
public hello = "hello"
}
}
@ classDecorator
class Greeter {
public property = "property"
public hello:string
constructor(m:string) {
this.hello = m
}
}
const targets = new Greeter("hello world")
console.log(targets)
// 打印结果
// Greeter {property: 'property', hello: 'hello', newProperety: 'new property'}
// hello: "hello"
// newProperety: "new property"
// property: "property"
// [[Prototype]]: Greeter
// ...
// 验证是否重写类的构造函数
function classConstrustor(target:any):any {
return class target {
public names = "xm"
public age = 18
}
}
@ classConstrustor
class people {
public hobby = "food"
public sex = 0
constructor(m:number) {
this.sex = m
}
}
const targets = new people(0)
console.log(targets)
// 打印结果
// 此处装饰器返回的类重写了类prople的构造函数
// 原本的hobby sex都被舍弃
// target {names: 'xm', age: 18}
// age: 18
// names: "xm"
// [[Prototype]]: Object
// ...
它会被应用到方法的 属性描述符上,可以用来监视,修改或者替换方法定义
通过Object.defineProperty方法设置
最低为ES5版本支持Object.defineProperty方法
Object.defineProperty(target,name,{ value:"xm",//属性值 writable:false,//是否可写 configurable:false,//是否可配置 enumerable:true,//是否可枚举 })
target:要设置的对象 name:对象的属性名 第三个参数:
Eg
ts// 属性描述符
interface ObjWithAnyKeys {
[key:string]:any
}
let obj2:ObjWithAnyKeys = {}
//使用属性修饰符
Object.defineProperty(obj2,"name",{
value:"xm",//属性值
writable:false,//是否可写
configurable:false,//是否可配置
enumerable:true,//是否可枚举
})
// console.log(obj2.name)// xm
//当writeable设置为false时
obj2.name = "ls"//报错,无法分配只读属性name
console.log(obj2.name)
//当writeable设置为true时
obj2.name = "ls"
console.log(obj2.name) // ls
// 当configurable设置为false时,不允许重定义name Cannot redefine property: name
Object.defineProperty(obj2,"name",{
value:"xm",//属性值
writable:false,//是否可写
configurable:true,//是否可配置
enumerable:true,//是否可枚举
})
// 当enumerable设置为true时
for(let keys in obj2){
console.log(keys) //name
}
方法装饰器在运行时传入下列3个参数:
1、对于类的实例成员
ts// 此处设置属性为不可枚举的
function enumerable(types:boolean) {
return (target:any,propertName:string,descriptor: PropertyDescriptor) => {
console.log(target)
console.log(target===ClassFN.prototype)// true 对于类的实例成员 target为类的实例对象
descriptor.enumerable = types
}
}
class ClassFN {
constructor( public age = 18) {
}
@enumerable(false) //改为true后
public getAge() {
return this.age
}
}
const classFn = new ClassFN(22)
for (let keys in classFn){
console.log(keys) //age ,更改后结果为age getAge
}
// 运行结果
// [LOG]: ClassFN: {}
// [LOG]: true
// [LOG]: "age"
2、对于类的私有成员
ts// 此处设置属性为不可枚举的
function enumerable(types:boolean) {
return (target:any,propertName:string,descriptor: PropertyDescriptor) => {
console.log(target)
console.log(target===ClassFN)// true 对于类的私有成员,为类本身
descriptor.enumerable = types
}
}
class ClassFN {
public age = 18
constructor( ) {
}
@enumerable(false) //改为true后
static getAge(){
return ClassFN.getAge
}
}
const classFn = new ClassFN()
for (let keys in classFn){
console.log(keys) //age ,更改后结果为age getAge
}
本文作者:RKLS
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!