详解如何在JavaScript中使用装饰器

Bella ·
更新时间:2024-11-10
· 326 次阅读

目录

安装

vite配置

webpack配置

使用

语法: @+函数名

类装饰器

带参数的修饰器

类成员装饰器

多个装饰器的执行顺序

应用

延迟

节流

防抖

Decorator装饰器是ES7的时候提案的特性,目前处于Stage 3候选阶段(2022年10月)。

装饰器简单来说就是修改类和类方法的语法糖,很多面向对象语言都有装饰器这一特性。

为了使用装饰器特性,我们需要用进行babel转义。这里需要用到的是@babel/plugin-proposal-decorators。

安装 npm install --save-dev @babel/plugin-proposal-decorators vite配置 import { defineConfig } from 'vite'; import babel from 'vite-plugin-babel'; export default defineConfig({ plugins: [ babelDev({ babelConfig: { plugin: ['@babel/plugin-proposal-decorators'] } }), // ... ], // ... }) webpack配置 module: { rules: [ { test: /\.(js|mjs|jsx|ts|tsx)$/, use: { loader: 'babel-loader', options: { // ... plugins: [ ['@babel/plugin-proposal-decorators', { 'legacy': true }], // ... ], // ... }, } // ... } ] } 使用

先来一图了解装饰器语法。

语法: @+函数名 @frozen class Foo { @throttle(500) expensiveMethod() {} } 类装饰器

参数target是类本身

function testable(target) { target.isTestable = true; } @testable class MyTestableClass { // ... } MyTestableClass.isTestable // true 带参数的修饰器

@+返回装饰器函数的表达式

function testable(isTestable) { return function(target) { target.isTestable = isTestable; } } @testable(true) class MyTestableClass {} MyTestableClass.isTestable // true @testable(false) class MyClass {} MyClass.isTestable // false 类成员装饰器

参数:

target:被修饰的类的原型对象

name:类成员的名字

descriptor:类成员的描述对象

function readonly(target, name, descriptor){ // descriptor对象原来的值如下 // { // value: specifiedFunction, // enumerable: false, // configurable: true, // writable: true // }; descriptor.writable = false; return descriptor; } class Person { @readonly name() { return `${this.first} ${this.last}` } } 多个装饰器的执行顺序

洋葱模型,先从外到内进入,然后由内向外执行

function dec(id){ console.log('evaluated', id); return (target, property, descriptor) => console.log('executed', id); } class Example { @dec(1) @dec(2) method(){} } // evaluated 1 // evaluated 2 // executed 2 // executed 1 应用 延迟 class Page { @delay(2000) onClick(a) { console.log("onClick"); } } function delay(time) { return function (target, key, descriptor) { const oldFunction = descriptor.value; descriptor.value = function() { setTimeout(() => { oldFunction.apply(this, arguments); }, time); } return descriptor; } } 节流

如果在定时器的时间范围内再次触发,则不予理睬,等当前定时器完成,才能启动下一个定时器任务

class Page { @throttle(2000) onClick(a) { console.log("onClick"); } } function throttle(time) { return function (target, key, descriptor) { const oldFunction = descriptor.value; let isLock = false; descriptor.value = function() { if(isLock) { return; } isLock = true; oldFunction.apply(this, arguments); setTimeout(() => { isLock = false; }, time); } return descriptor; } } 防抖

每次事件触发则删除原来的定时器,建立新的定时器。

class Page { @debounce(2000) onClick(a) { console.log("onClick"); } } function debounce(time) { return function (target, key, descriptor) { const oldFunction = descriptor.value; let timer = null; descriptor.value = function () { clearTimeout(timer); timer = setTimeout(() => { oldFunction.apply(this, arguments) }, time); }; return descriptor; } }

到此这篇关于详解如何在JavaScript中使用装饰器的文章就介绍到这了,更多相关JavaScript使用装饰器内容请搜索软件开发网以前的文章或继续浏览下面的相关文章希望大家以后多多支持软件开发网!



装饰器 JavaScript

需要 登录 后方可回复, 如果你还没有账号请 注册新账号