装饰器在angular中大量使用,有必要单独拎出来说一下。
装饰器顾名思义,就是装饰用的,装饰什么呢?
主要是类、属性和方法。
属性装饰器
顾名思义,就是装饰类的属性的。
比如有个用户名属性username,我希望在模板打印时,前面自动加上"我的名字叫jack"。
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-decorate',
templateUrl: './decorate.component.html',
styleUrls: ['./decorate.component.scss']
})
export class DecorateComponent implements OnInit {
username = 'jack'
constructor() { }
ngOnInit(): void {
}
}
大家想想,如果不用装饰器我们应该如何来做呢?
其实也很简单,声明一个函数,将属性传入进去处理一下就可以了对吧?
装饰器其实就是这样的函数,它会接收目标参数,然后处理完成后返回。
import { Component, OnInit } from '@angular/core';
import {attrDecorate} from '../../../utils/attrDecorate'
@Component({
selector: 'app-decorate',
templateUrl: './decorate.component.html',
styleUrls: ['./decorate.component.scss']
})
export class DecorateComponent implements OnInit {
@attrDecorate() username = 'jack'
constructor() { }
ngOnInit(): void {
}
}
这里我声明了@attrDecorate()这个装饰器,这里并不需要额外传参,因此形参传空就行。
装饰器其实很简单,就是导出一个函数。
attrDecorate.js:
export function attrDecorate(){
return (target,key)=> {
console.log(target,key) //target:;当前对象,key:属性
let val = target[key];
Object.defineProperty(target,key,{
get(){
return val
},
set(value){
val = '我的名字叫'+value
}
})
}
}
我们要注意一下装饰器返回的内函数,形参其实跟Object.defineProperty的形参是一致的:
第一个函数是目标对象,
第二个参数是属性信息,
第三个是属性描述符。
但属性装饰器的话,描述符是空的。
方法装饰器
import { Component, OnInit } from '@angular/core';
import {attrDecorate} from '../../../utils/attrDecorate'
import {methodDecorate} from '../../../utils/methodDecorate'
@Component({
selector: 'app-decorate',
templateUrl: './decorate.component.html',
styleUrls: ['./decorate.component.scss']
})
export class DecorateComponent implements OnInit {
//属性装饰器
@attrDecorate() username = 'jack'
//方法装饰器
@methodDecorate('确定删除吗?')
del(){
console.log('delete ok');
}
constructor() { }
ngOnInit(): void {
}
}
这里对del()方法进行装饰:
export function methodDecorate(msg){
return (target,key,dec)=>{//target:当前对象,key:函数名, dec:{writable: true, enumerable: false, configurable: true, value: ƒ}
console.log(target);
console.log(key);
console.log(dec);
let oldFn = dec.value;
dec.value = function(){
let flag = window.confirm(msg);//加上确认弹出框
if(flag) {
oldFn();
}
}
}
}
类装饰器
import { Component, OnInit } from '@angular/core';
import {attrDecorate} from '../../../utils/attrDecorate'
import {methodDecorate} from '../../../utils/methodDecorate'
import {classDecorate} from '../../../utils/classDecorate'
@classDecorate({
test:'测试一下'
})
@Component({
selector: 'app-decorate',
templateUrl: './decorate.component.html',
styleUrls: ['./decorate.component.scss']
})
export class DecorateComponent implements OnInit {
//属性装饰器
@attrDecorate() username = 'jack'
//方法装饰器
@methodDecorate('确定删除吗?')
del(){
console.log('delete ok');
}
constructor() { }
ngOnInit(): void {
}
}
classDecorate.js:
export function classDecorate(params){
console.log(params);
return (target)=>{
console.log(target);这里只有一个目标对象
}
}
之前学的组件通信,@Input()和@Output()都是属性装饰器,子组件需要对传递过来的信息进行加工处理,而@Component是类装饰器,需要对当前类进行加工,将名称、模板、样式等信息注入到类里面进去,现在看看是不是就很清楚了。
网友评论