当前位置:首页 > 科技  > 软件

5分钟带你了解【前端装饰器】,“高大上”的“基础知识”

来源: 责编: 时间:2024-05-08 09:20:36 96观看
导读前言大家好,我是林三心,用最通俗易懂的话讲最难的知识点是我的座右铭,基础是进阶的前提是我的初心。基本介绍装饰器是一种以 @ 符号开头的特殊语法,放在目标代码的前面用于包装或扩展代码功能。JavaScript 的装饰器语法目

前言

大家好,我是林三心,用最通俗易懂的话讲最难的知识点是我的座右铭,基础是进阶的前提是我的初心。4Qa28资讯网——每日最新资讯28at.com

基本介绍

装饰器是一种以 @ 符号开头的特殊语法,放在目标代码的前面用于包装或扩展代码功能。JavaScript 的装饰器语法目前仍处于提案阶段,现阶段使用的话需要通过 bable 等方式进行编译之后,才能在浏览器正常运行。装饰器分为两种:类装饰器,类成员装饰器,分别用于装饰我们的类以及类的成员。4Qa28资讯网——每日最新资讯28at.com

基本使用(类装饰器)

class MyClass {  constructor() {}}

比如现在有一个类或者函数 MyClass,它的身上没有任何的东西,但是我想要给他加一个 log 方法,那我们应该怎么做呢?很多人回想说,直接在它身上加一个 log 方法即可~4Qa28资讯网——每日最新资讯28at.com

class MyClass {  constructor() {}    log() {}}

但是这么做的话,一个 class 是能做,那如果要给 1000 个 class 加上 log方法呢?那岂不是每一个都得写~很麻烦,这个时候可以使用 装饰器 去拓展每一个 class4Qa28资讯网——每日最新资讯28at.com

  • 可以拓展原型方法
  • 可以拓展静态属性

装饰器接收的参数是装饰的目标类,这里的 cls 就是 MyClass4Qa28资讯网——每日最新资讯28at.com

function addConcole(target) {  // 拓展原型方法  target.prototype.log = function(msg) {    console.log(`[${new Date()} ${msg}`);  };  // 拓展静态属性  target.myName = '一个类'  return target;}@addConcoleclass MyClass {  constructor() {}}const myObj = new MyClass();myObj.log('林三心');// [Sat Jul 08 2023 17:31:55 GMT+0800 (中国标准时间) 林三心console.log(MyClass.myName)// 一个类

应用场景

Node路由请求Url(类成员装饰器)

我们在使用一些 Node 的框架时,在写接口的时候,我们可能会经常看到这样的代码4Qa28资讯网——每日最新资讯28at.com

  • 当我们请求路径是 GET doc 时会匹配到findDocById
  • 当我们请求路径是 POST doc 时会匹配到createDoc
class Doc {  @Get('doc')  async findDocById(id) {}    @Post('doc')  async createDoc(data) {}}

其实这个 @Get 和 @Post ,是框架提供给我们的 类成员装饰器,是的,类成员也能使用装饰器,类成员装饰器接收三个参数:4Qa28资讯网——每日最新资讯28at.com

  • target 是目标类的原型对象
  • key 表示目标类成员的键名
  • descriptor 是一个属性描述符对象,它包含目标类成员的属性特性(例如 value、writable 等)
function Get(path) {  return function(target, key, descriptor) {    console.log({      target,      key,      descriptor    })  }}

图片图片4Qa28资讯网——每日最新资讯28at.com

他的基本实现原理大概是这样的4Qa28资讯网——每日最新资讯28at.com

function Get(routePath) {  return function(target, key, descriptor) {    const originalMethod = descriptor.value; // 保存原始方法    descriptor.value = function() {      // 在原始方法执行前加入逻辑      console.log('处理 Get 请求,路由路径: ' + routePath);      // 执行原始方法      const result = originalMethod.apply(this, arguments);      // 在原始方法执行后加入逻辑      console.log('Get 请求处理完成');      return result;    };    return descriptor;  };}

接口权限控制(类成员装饰器叠加)

上面我们介绍了一下 Nodejs Url 的路由匹配基本原理,但是这是不够的,因为很多接口还需要权限控制,比如:4Qa28资讯网——每日最新资讯28at.com

  • GET doc 接口只能 管理员 才能访问
  • POST doc 接口只能 超级管理员 才能访问

这也可以用装饰器来实现,并且装饰器是可以叠加的~4Qa28资讯网——每日最新资讯28at.com

class Doc {  @Get('doc')  @Role('admin')  async findDocById(id) {}    @Post('doc')  @Role('superAdmin')  async createDoc(data) {}}

装饰器叠加的执行顺序是 从下往上 的~我们可以看一下下面的例子,发现输出顺序是4Qa28资讯网——每日最新资讯28at.com

  • 2
  • 1
function A () {  console.log(1)}function B () {  console.log(2)}class Doc {  @A  @B  async test() {}}

至于权限控制的装饰器实现,需要根据不同业务去实现,我这里就粗略实现一下4Qa28资讯网——每日最新资讯28at.com

function Role(permissions) {  return function(target, key, descriptor) {    const originalMethod = descriptor.value; // 保存原始方法    descriptor.value = function() {      // 在原始方法执行前进行权限验证      const user = getCurrentUser(); // 获取当前用户信息      // 检查用户是否拥有所需权限      const hasPermission = checkUserPermissions(user, permissions);      if (!hasPermission) {        // 如果用户没有权限,则抛出错误或执行其他处理        throw new Error('无权限访问该接口');      }      // 执行原始方法      const result = originalMethod.apply(this, arguments);      return result;    };    return descriptor;  };}

记录日志的装饰器

我们想要在执行某个函数的时候,记录一下4Qa28资讯网——每日最新资讯28at.com

  • 函数调用时间
  • 函数调用参数

这个时候我们也可以使用装饰器来完成,非常方便!!!4Qa28资讯网——每日最新资讯28at.com

// 日志装饰器函数function logDecorator(target, key, descriptor) {  const originalMethod = descriptor.value; // 保存原始方法  descriptor.value = function(...args) {    console.log(`调用函数:${key}`);    console.log(`参数:${JSON.stringify(args)}`);    // 执行原始方法    const result = originalMethod.apply(this, args);    console.log(`返回值:${result}`);    return result;  };  return descriptor;}// 示例类class Example {  @logDecorator  greet(name) {    return `Hello, ${name}!`;  }}// 测试const example = new Example();example.greet('林三心');

缓存的装饰器

如果我们执行一个方法,获取返回值需要经过一系列的计算,非常耗时间,那么我们可以判断入参,第一次时计算完缓存起来,第二次的时候如果还是这个入参,就直接从缓存中去拿,这个操作也可以使用装饰器去完成4Qa28资讯网——每日最新资讯28at.com

// 缓存装饰器函数function cacheDecorator(target, key, descriptor) {  const cache = {}; // 缓存对象  const originalMethod = descriptor.value; // 保存原始方法  descriptor.value = function(...args) {    const cacheKey = JSON.stringify(args); // 生成缓存键    if (cacheKey in cache) {      console.log('从缓存中获取结果');      return cache[cacheKey]; // 直接返回缓存结果    }    // 执行原始方法    const result = originalMethod.apply(this, args);    console.log('将结果缓存起来');    cache[cacheKey] = result; // 缓存结果    return result;  };  return descriptor;}// 示例类class Example {  @cacheDecorator  getValue(key) {    console.log('执行函数逻辑');    return key + Math.random(); // 模拟复杂的计算逻辑  }}// 测试const example = new Example();console.log(example.getValue('foo'));console.log(example.getValue('foo')); // 从缓存中获取结果

防抖节流的装饰器

对于防抖节流,我们平时可能会这么去做4Qa28资讯网——每日最新资讯28at.com

class C {  onClick = debounce(fn, 100)}

但是这么做的话会使这个函数不好拓展,所以使用装饰器真的很方便4Qa28资讯网——每日最新资讯28at.com

// 防抖装饰器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;  }}// 节流装饰器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 C {  @debounce(1000)  onClick() {}    @throttle(1000)  onScroll() {}}


4Qa28资讯网——每日最新资讯28at.com

本文链接://www.dmpip.com//www.dmpip.com/showinfo-26-87263-0.html5分钟带你了解【前端装饰器】,“高大上”的“基础知识”

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 关于 CSS 选择器权重,99% 的人都理解错了!

下一篇: 为什么要看 Python 源码?它的结构长什么样子?

标签:
  • 热门焦点
  • 6月安卓手机性能榜:vivo/iQOO霸占旗舰排行榜前三

    6月安卓手机性能榜:vivo/iQOO霸占旗舰排行榜前三

    2023年上半年已经正式过去了,我们也迎来了安兔兔V10版本,在新的骁龙8Gen3和天玑9300发布之前,性能榜的榜单大体会以骁龙8Gen2和天玑9200+为主,至于那颗3.36GHz的骁龙8Gen2领先
  • 5月iOS设备性能榜:M1 M2依旧是榜单前五

    5月iOS设备性能榜:M1 M2依旧是榜单前五

    和上个月一样,没有新品发布的iOS设备性能榜的上榜设备并没有什么更替,仅仅只有跑分变化而产生的排名变动,刚刚开始的苹果WWDC2023,推出的产品也依旧是新款Mac Pro、新款Mac Stu
  • Flowable工作流引擎的科普与实践

    Flowable工作流引擎的科普与实践

    一.引言当我们在日常工作和业务中需要进行各种审批流程时,可能会面临一系列技术和业务上的挑战。手动处理这些审批流程可能会导致开发成本的增加以及业务复杂度的上升。在这
  • 如何通过Python线程池实现异步编程?

    如何通过Python线程池实现异步编程?

    线程池的概念和基本原理线程池是一种并发处理机制,它可以在程序启动时创建一组线程,并将它们置于等待任务的状态。当任务到达时,线程池中的某个线程会被唤醒并执行任务,执行完任
  • 中国家电海外掘金正当时|出海专题

    中国家电海外掘金正当时|出海专题

    作者|吴南南编辑|胡展嘉运营|陈佳慧出品|零态LT(ID:LingTai_LT)2023年,出海市场战况空前,中国创业者在海外纷纷摩拳擦掌,以期能够把中国的商业模式、创业理念、战略打法输出海外,他们依
  • 东方甄选单飞:有些鸟注定是关不住的

    东方甄选单飞:有些鸟注定是关不住的

    文/彭宽鸿编辑/罗卿东方甄选创始人俞敏洪带队的“7天甘肃行”直播活动已在近日顺利收官。成立后一年多时间里,东方甄选要脱离抖音自立门户的传闻不绝于耳,“7
  • 东方甄选单飞:有些鸟注定是关不住的

    东方甄选单飞:有些鸟注定是关不住的

    作者:彭宽鸿来源:华尔街科技眼‍‍‍‍‍‍‍‍‍‍东方甄选创始人俞敏洪带队的“7天甘肃行”直播活动已在近日顺利收官。成立后一
  • iQOO Neo8系列或定档5月23日:首发天玑9200+ 安卓跑分王者

    iQOO Neo8系列或定档5月23日:首发天玑9200+ 安卓跑分王者

    去年10月,iQOO推出了iQOO Neo7系列机型,不仅搭载了天玑9000+,而且是同价位唯一一款天玑9000+直屏旗舰,一经上市便受到了用户的广泛关注。在时隔半年后,
  • 朋友圈可以修改可见范围了 苹果用户可率先体验

    朋友圈可以修改可见范围了 苹果用户可率先体验

    近日,iOS用户迎来微信8.0.27正式版更新,除了可更换二维码背景外,还新增了多项实用功能。在新版微信中,朋友圈终于可以修改可见范围,简单来说就是已发布的朋友圈
Top
Baidu
map