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

目录
  • 安装
  • 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使用装饰器内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • JavaScript装饰器函数(Decorator)实例详解

    本文实例讲述了JavaScript装饰器函数(Decorator).分享给大家供大家参考,具体如下: 装饰器函数(Decorator)用于给对象在运行期间动态的增加某个功能,职责等.相较通过继承的方式来扩充对象的功能,装饰器显得更加灵活,首先,我们可以动态给对象选定某个装饰器,而不用hardcore继承对象来实现某个功能点.其次:继承的方式可能会导致子类繁多,仅仅为了增加某一个单一的功能点,显得有些多余了. 下面给出几个常用的装饰器函数示例,相关代码请查看github. 1 动态添加onload

  • 一文理解JavaScript装饰器模式

    装饰器模式想必大家并不陌生:它允许向一个现有的对象添加新的功能,同时又不改变其结构,属于结构型模式,它是作为现有的类的一个包装. 这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能. 在 JS 中,装饰器(Decorator)是ES7中的一个新语法,它可以对​​类.方法.属性​​进行​​修饰​​,从而进行一些相关功能定制.它的写法与Java的注解(Annotation)非常相似,但是功能还是有很大区别. 代码示例: 不使用装饰器: const log

  • JS装饰者模式和TypeScript装饰器

    装饰者模式介绍 装饰者模式(Decorator Pattern)也称为装饰器模式,在不改变对象自身的基础上,动态增加额外的职责.属于结构型模式的一种. 使用装饰者模式的优点:把对象核心职责和要装饰的功能分开了.非侵入式的行为修改. 举个例子来说,原本长相一般的女孩,借助美颜功能,也能拍出逆天的颜值.只要善于运用辅助的装饰功能,开启瘦脸,增大眼睛,来点磨皮后,咔嚓一拍,惊艳无比. 经过这一系列叠加的装饰,你还是你,长相不增不减,却能在镜头前增加了多重美.如果你愿意,还可以尝试不同的装饰风格,只要装

  • JavaScript装饰器的实现原理详解

    目录 装饰器的常见作用 装饰类的属性 装饰类 注意 实例应用 最近在使用TS+Vue的开发模式,发现项目中大量使用了装饰器,看得我手足无措,今天特意研究一下实现原理,方便自己理解这块知识点. 装饰器的常见作用 装饰一个类的属性 装饰一个类 装饰器只能针对类和类的属性,不能直接作用于函数,因为存在函数提升. 下面我们针对这两种情况进行举例阐述. 装饰类的属性 function readonly(target, name, descriptor) { discriptor.writable = fa

  • JS装饰器函数用法总结

    在 ES6 中增加了对类对象的相关定义和操作(比如 class 和 extends ),这就使得我们在多个不同类之间共享或者扩展一些方法或者行为的时候,变得并不是那么优雅.这个时候,我们就需要一种更优雅的方法来帮助我们完成这些事情. 什么是装饰器 Python 的装饰器 在面向对象(OOP)的设计模式中,decorator被称为装饰模式.OOP的装饰模式需要通过继承和组合来实现,而Python除了能支持 OOP 的 decorator 外,直接从语法层次支持 decorator. 如果你熟悉 p

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

    目录 安装 vite配置 webpack配置 使用 语法: @+函数名 类装饰器 带参数的修饰器 类成员装饰器 多个装饰器的执行顺序 应用 延迟 节流 防抖 Decorator装饰器是ES7的时候提案的特性,目前处于Stage 3候选阶段(2022年10月). 装饰器简单来说就是修改类和类方法的语法糖,很多面向对象语言都有装饰器这一特性. 为了使用装饰器特性,我们需要用进行babel转义.这里需要用到的是@babel/plugin-proposal-decorators. 安装 npm inst

  • 详解如何在Javascript中使用Object.freeze()

    Object.freeze() Object.freeze() 方法可以冻结一个对象.一个被冻结的对象再也不能被修改:冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性.可配置性.可写性,以及不能修改已有属性的值.此外,冻结一个对象后该对象的原型也不能被修改.freeze() 返回和传入的参数相同的对象 用法 const objectExample = { prop1: 20, prop2: "羊先生" }; // 默认情况下,我们可以根据需

  • 详解如何在pyqt中通过OpenCV实现对窗口的透视变换

    窗口的透视变换效果    当我们点击Win10的UWP应用中的小部件时,会发现小部件会朝着鼠标点击位置凹陷下去,而且不同的点击位置对应着不同的凹陷情况,看起来就好像小部件在屏幕上不只有x轴和y轴,甚至还有一个z轴.要做到这一点,其实只要对窗口进行透视变换即可.下面是对Qt的窗口和按钮进行透视变换的效果: 具体代码    1.下面先定义一个类,它的作用是将传入的 QPixmap 转换为numpy 数组,然后用 opencv 的 warpPerspective 对数组进行透视变换,最后再将 nump

  • 详解如何在C#中使用投影(Projection)

    投影(Projection) 是一种可以将查询结果进行 塑性 的一种操作,你可以使用 投影 将一个 object 转成仅包含你需要属性的新对象,这篇文章中,我们就一起看看如何使用 投影 功能. C# 中的投影 LINQ 集成查询中有两个支持投影的扩展方法,分别为: Select 和 SelectMany 操作,可以用它们投影单个或者多个属性,或者投影查询的结果集到一个新的匿名类型中,还可以在投影的过程中执行: 再计算,过滤,或者其他一些必要的操作. Select 投影 为了演示目的,我先构造一个

  • 详解如何在Flutter中集成华为认证服务

    最近发现华为AGC认证服务支持Flutter框架了,期待这个平台的支持已经很久了,所以迫不及待接入了,关联了自己的邮箱等账号. 集成步骤 安装flutter环境 a) 下载Flutter sdk包,地址:https://flutter.dev/docs/get-started/install/windows 将压缩包解压到任意文件夹,例如D:\Flutter b) 将flutter命令文件添加到环境变量中,此处我添加的Path为D:\Flutter\flutter_windows_1.22.2-

  • 详解如何在Java中调用Python程序

    Java中调用Python程序 1.新建一个Maven工程,导入如下依赖 <dependency> <groupId>org.python</groupId> <artifactId>jython-standalone</artifactId> <version>2.7.0</version> </dependency> 2.在java中直接执行python代码片段 import org.python.util

  • 详解如何在Java中实现堆排序算法

    目录 算法描述 实现代码 测试代码 算法描述 堆排序算法的描述如下: 将待排序的数组调整为最大堆,此时未排序的长度 N 为数组的长度,调整的过程就是倒序将数组的前 N/2 个元素下沉的过程,每次下沉都会将较大的元素带到上面,最终将数组变为最大堆: 弹出最大堆的堆顶元素并将其移动到数组的最后面,将原本最后面的元素放到堆顶,然后将未排序的长度 N - 1,调整数组的前 N 个元素为最大堆: 重复步骤 2 直到未排序的长度为 0. 实现代码 package com.zhiyiyo.collection

  • 详解如何在Flutter中获取设备标识符

    目录 使用 platform_device_id 应用预览 代码 使用 device_info_plus 应用预览 代码 结论 本文将引导您完成 2 个示例,演示如何在 Flutter 中获取设备标识符 使用 platform_device_id 如果您只需要运行应用程序的设备的 id,最简单快捷的解决方案是使用platform_device_id包.它适用于 Android (AndroidId).iOS (IdentifierForVendor).Windows (BIOS UUID).ma

  • 详解如何在SpringBoot中自定义参数解析器

    目录 前言 1.自定义参数解析器 2.PrincipalMethodArgumentResolver 3.RequestParamMapMethodArgumentResolver 4.小结 前言 在一个 Web 请求中,参数我们无非就是放在地址栏或者请求体中,个别请求可能放在请求头中. 放在地址栏中,我们可以通过如下方式获取参数: String javaboy = request.getParameter("name "); 放在请求体中,如果是 key/value 形式,我们可以通

  • 详解如何在Vue中动态添加类名

    目录 静态和动态类 有条件的类名 使用数组语法 使用对象语法 与自定义组件一起使用 快速生成类名 使用计算属性来简化类 能够向组件添加动态类名是非常强大的功能.它使我们可以更轻松地编写自定义主题,根据组件的状态添加类,还可以编写依赖于样式的组件的不同变体. 添加动态类名与在组件中添加 prop :class="classname"一样简单.无论classname的计算结果是什么,都将是添加到组件中的类名. 当然,对于Vue中的动态类,我们可以做的还有很多.在本文中,我们将讨论很多内容:

随机推荐