TypeScript 装饰器入门核心用法

一、什么是装饰器?

装饰器就是普通函数 ,用 @装饰器名 贴在类、方法、属性上,作用就是给被装饰的东西加额外功能,仅此而已。

二、最基础用法:类装饰器

直接贴在类上,函数唯一参数是被装饰类的构造函数,最简单的例子:给类加静态属性。

typescript 复制代码
// 定义装饰器函数:给类加版本号
function addVersion(target) {
  target.version = '1.0.0'; // 给类挂载静态属性
}

// 用@贴在类上,完成装饰
@addVersion
class MyClass {}

// 直接使用装饰器加的属性
console.log(MyClass.version); // 输出:1.0.0

核心逻辑:@addVersion 等价于 addVersion(MyClass),把类传给装饰器函数就行。

三、最常用用法:方法装饰器

贴在类的方法上,日常用得最多,函数有 3 个固定参数:不用死记含义,跟着案例用就会。

简单案例1:给方法加日志

执行方法时,自动打印"方法被调用了",不用在方法里写重复代码。

typescript 复制代码
// 方法装饰器:打印方法调用日志
function showLog(target, name, descriptor) {
  // 保存原方法
  const oldFn = descriptor.value;
  // 重写方法,加日志逻辑
  descriptor.value = function() {
    console.log(`【日志】${name}方法被调用了`);
    oldFn.apply(this); // 执行原来的方法
  };
}

class MyClass {
  // 装饰器贴在方法上
  @showLog
  sayHi() {
    console.log('hello TS');
  }
}

new MyClass().sayHi();
// 输出:【日志】sayHi方法被调用了 → hello TS

简单案例2:禁止方法被修改

让方法只读,不能被重新赋值,避免误改方法逻辑。

typescript 复制代码
// 方法装饰器:禁止方法修改
function noChange(target, name, descriptor) {
  descriptor.writable = false; // 设为不可写
}

class MyClass {
  @noChange
  fn() {
    console.log('不能改我');
  }
}

const obj = new MyClass();
obj.fn = () => {}; // 报错:无法分配到 "fn",因为它是只读属性

四、属性装饰器:给属性加默认值

贴在类的属性上,函数有 2 个参数,最简单的用法:给属性设置默认值,不用在构造函数里初始化。

typescript 复制代码
// 属性装饰器:设置默认值
function setDefault(val) {
  return function(target, name) {
    target[name] = val;
  };
}

class MyClass {
  // 贴在属性上,传默认值
  @setDefault('张三')
  name;

  @setDefault(20)
  age;
}

console.log(new MyClass().name); // 输出:张三
console.log(new MyClass().age); // 输出:20

五、装饰器工厂:给装饰器传参

想给装饰器传自定义参数(比如日志加前缀、默认值自定义),就写装饰器工厂------本质是「返回装饰器的函数」,写法超简单,看案例就会。

案例:带前缀的日志装饰器

让日志有自定义前缀,不用写多个装饰器函数。

typescript 复制代码
// 装饰器工厂:接收自定义前缀
function log(prefix) {
  // 返回真正的装饰器函数
  return function(target, name, descriptor) {
    const oldFn = descriptor.value;
    descriptor.value = function() {
      console.log(`【${prefix}】${name}方法执行了`);
      oldFn.apply(this);
    };
  };
}

class MyClass {
  // 传参使用:自定义前缀"接口请求"
  @log('接口请求')
  getData() {}

  // 传参使用:自定义前缀"操作"
  @log('操作')
  saveData() {}
}

new MyClass().getData(); // 输出:【接口请求】getData方法执行了
new MyClass().saveData(); // 输出:【操作】saveData方法执行了

六、必记规则:多个装饰器的执行顺序

一个类/方法上贴多个装饰器时,从下往上执行------谁离被装饰的东西近,谁先执行。

typescript 复制代码
// 定义两个简单装饰器
function A(target) {
  console.log('执行装饰器A');
  return target;
}
function B(target) {
  console.log('执行装饰器B');
  return target;
}

// B离类更近,先执行;A后执行
@A
@B
class MyClass {}

// 运行结果:先打印「执行装饰器B」,再打印「执行装饰器A」

等价理解:MyClass = A(B(MyClass)),先执行内层的 B,再执行外层的 A。

七、使用前提:开启TS配置

装饰器是 TS 实验性特性,必须在 tsconfig.json 里加一行配置,否则报错,就加这一个核心项就行:

json 复制代码
{
  "compilerOptions": {
    "experimentalDecorators": true, // 必须开启,启用装饰器
    "target": "ES5" // 项目基本配置,一般都有
  }
}
相关推荐
阿蒙Amon2 小时前
TypeScript学习-第1章:入门
javascript·学习·typescript
winfredzhang2 小时前
实战复盘:如何用 HTML+JS+AI 打造一款“影迹”智能影视管理系统
javascript·html·json·加载·搜索·保存·电影接口
集成显卡2 小时前
Lucide Icons:一套现代、轻量且可定制的 SVG 图标库
前端·ui·图标库·lucide
pas1363 小时前
37-mini-vue 解析插值
前端·javascript·vue.js
十里-4 小时前
vue.js 2前端开发的项目通过electron打包成exe
前端·vue.js·electron
雨季6664 小时前
构建 OpenHarmony 简易文字行数统计器:用字符串分割实现纯文本结构感知
开发语言·前端·javascript·flutter·ui·dart
雨季6664 小时前
Flutter 三端应用实战:OpenHarmony 简易倒序文本查看器开发指南
开发语言·javascript·flutter·ui
小北方城市网4 小时前
Redis 分布式锁高可用实现:从原理到生产级落地
java·前端·javascript·spring boot·redis·分布式·wpf
console.log('npc')5 小时前
vue2 使用高德接口查询天气
前端·vue.js