鸿蒙Next-方法装饰器以及防抖方法注解实现

以下是关于 鸿蒙Next(HarmonyOS NEXT)中 MethodDecorator 的详细介绍及使用指南,结合了多个技术来源的实践总结:


一、MethodDecorator 的概念与作用

MethodDecorator 是鸿蒙Next框架中用于装饰类方法的装饰器,属于 ArkUI 装饰器体系 的一部分。它允许开发者为类方法动态添加元数据或功能扩展,例如实现方法拦截、状态监听、日志记录等场景。通过装饰器,开发者能以声明式的方式增强代码的可维护性和复用性。

核心特点:
  1. 非侵入式增强:在不修改原方法逻辑的前提下,通过装饰器注入额外逻辑。

  2. 元数据绑定:可为方法添加配置信息(如参数校验规则、权限控制标记)。

  3. 与状态管理联动:常与 @State@Prop 等状态装饰器结合,实现数据变化响应。


二、MethodDecorator 的语法与使用示例

1. 基本语法
function MyMethodDecorator(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
  // 装饰器逻辑:修改或增强原方法
  const originalMethod = descriptor.value;
  descriptor.value = function (...args: any[]) {
    console.log(`方法 ${propertyKey} 被调用`);
    return originalMethod.apply(this, args);
  };
  return descriptor;
}

class MyClass {
  @MyMethodDecorator
  myMethod() {
    // 原方法逻辑
  }
}
2. 常见使用场景

(1) 方法调用日志记录

function LogMethod() {
  return function (target: any, methodName: string, descriptor: PropertyDescriptor) {
    const original = descriptor.value;
    descriptor.value = function (...args: any[]) {
      console.log(`调用方法:${methodName},参数:${JSON.stringify(args)}`);
      return original.apply(this, args);
    };
  };
}

@Component
struct MyComponent {
  @LogMethod()
  handleClick() {
    // 处理点击事件
  }
}

(2) 状态监听与联动通过 @Watch 装饰器(内置的 MethodDecorator)监听状态变量变化并触发方法:

@Component
struct MyComponent {
  @State count: number = 0;

  @Watch('count') // 监听 count 变化
  onCountChanged(newValue: number, oldValue: number) {
    console.log(`count 从 ${oldValue} 变为 ${newValue}`);
  }

  build() {
    Button('增加').onClick(() => this.count++);
  }
}

此例中,@Watch 装饰器会在 count 变化时自动调用 onCountChanged 方法。

(3) 点击事件防抖

//period间隔时间
@Debounce(2000)
clickMethod(){
}
function Debounce(period: number = 750): MethodDecorator {
  return function (
      target: object,
      propertyKey: string,
      descriptor: PropertyDescriptor
  ): PropertyDescriptor {
    const originalMethod = descriptor.value
    let timeId: number = 0
    descriptor.value = function (...args: object[]): void {
      if (timeId !== 0) {
        clearTimeout(timeId)
      }
      timeId = setTimeout(() => {
        originalMethod.apply(this, args)
        timeId = 0
      },
        period
      )
    }
    return descriptor
  }
}

(4) 监听某个方法的耗时

function MonitorCostTime(): MethodDecorator {
  return function (target: object,
    propertyKey: string,
    descriptor: PropertyDescriptor) {
    const originMethod = descriptor.value

    descriptor.value = function (...args: object[]) {
      let startTime = systemDateTime.getTime()
      const result = originMethod.apply(this, args); // 调用原始方法
      const endTime = systemDateTime.getTime(); // 获取方法执行后的时间
      hilog.error(hilog.LogLevel.ERROR, "monitorCostTime", `方法消耗的时间为:${endTime - startTime}s`)
      return result;
    }
    return descriptor
  }
}

(5) 权限控制

function CheckPermission(permission: string) {
  return function (target: any, methodName: string, descriptor: PropertyDescriptor) {
    const original = descriptor.value;
    descriptor.value = function (...args: any[]) {
      if (hasPermission(permission)) {
        return original.apply(this, args);
      } else {
        console.error('无权限执行此操作');
      }
    };
  };
}

class UserService {
  @CheckPermission('admin')
  deleteUser() {
    // 删除用户逻辑
  }
}

三、与 ArkUI 框架的深度集成

1. 生命周期方法装饰

鸿蒙Next的组件生命周期方法(如 aboutToAppearaboutToDisappear)本质上是内置的 MethodDecorator,开发者可通过自定义装饰器扩展生命周期行为:

function TrackLifecycle() {
  return function (target: any, methodName: string, descriptor: PropertyDescriptor) {
    const original = descriptor.value;
    descriptor.value = function (...args: any[]) {
      console.log(`组件生命周期方法 ${methodName} 被触发`);
      return original.apply(this, args);
    };
  };
}

@Component
struct MyComponent {
  @TrackLifecycle()
  aboutToAppear() {
    // 组件初始化逻辑
  }
}
2. 动画与交互增强

结合 animateTo 方法,可通过装饰器封装动画逻辑:

function FadeAnimation(duration: number) {
  return function (target: any, methodName: string, descriptor: PropertyDescriptor) {
    const original = descriptor.value;
    descriptor.value = function (...args: any[]) {
      animateTo({
        duration: duration,
        onFinish: () => original.apply(this, args)
      }, () => {
        this.opacity = 0;
      });
    };
  };
}

@Component
struct AnimatedButton {
  @State opacity: number = 1;

  @FadeAnimation(300)
  handleClick() {
    // 点击后的业务逻辑
  }

  build() {
    Button('点击').opacity(this.opacity).onClick(() => this.handleClick());
  }
}

四、注意事项与最佳实践

  1. 装饰器执行顺序
    多个装饰器按 从下到上 的顺序执行(装饰器工厂函数从外到内)。

  2. 避免副作用
    装饰器应保持无状态,避免修改全局变量或依赖外部环境。

  3. 性能优化
    高频调用的方法慎用复杂装饰器逻辑,必要时通过缓存优化。

  4. 兼容性
    确保装饰器与鸿蒙Next的 API 版本兼容,避免使用实验性特性。


五、扩展应用:自定义高级装饰器

1. 异步方法拦截
function Retry(maxAttempts: number) {
  return function (target: any, methodName: string, descriptor: PropertyDescriptor) {
    const original = descriptor.value;
    descriptor.value = async function (...args: any[]) {
      let attempts = 0;
      while (attempts < maxAttempts) {
        try {
          return await original.apply(this, args);
        } catch (error) {
          attempts++;
          console.log(`重试第 ${attempts} 次`);
        }
      }
      throw new Error('操作失败');
    };
  };
}

class ApiService {
  @Retry(3)
  async fetchData() {
    // 网络请求逻辑
  }
}
2. 参数校验
function ValidateParams(...validators: Function[]) {
  return function (target: any, methodName: string, descriptor: PropertyDescriptor) {
    const original = descriptor.value;
    descriptor.value = function (...args: any[]) {
      validators.forEach((validator, index) => {
        if (!validator(args[index])) {
          throw new Error(`参数 ${index} 校验失败`);
        }
      });
      return original.apply(this, args);
    };
  };
}

class Calculator {
  @ValidateParams(
    (x: number) => !isNaN(x),
    (y: number) => y !== 0
  )
  divide(x: number, y: number) {
    return x / y;
  }
}

总结

MethodDecorator 是鸿蒙Next开发中实现 代码复用 和 逻辑解耦 的重要工具。通过合理使用内置装饰器(如 @Watch)和自定义装饰器,开发者可以显著提升代码的可维护性,同时实现复杂的业务逻辑与交互效果。实际开发中需结合具体场景选择装饰器策略,并注意性能与兼容性问题。

关注我获取更多知识或者投稿

d625635cc096aea7ecdeace5281677e2.jpeg

335e9bf34e8e735ab06ed9e857cd1c51.jpeg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/977919.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

快速入门——状态管理VueX

Vuex介绍 状态管理 每一个Vuex应用的核心都是一个store&#xff0c;与普通的全局对象不同的是&#xff0c;基于Vue数据与视图绑定的特点&#xff0c;当store中的状态发生变化时&#xff0c;与之绑定的视图也会被重新渲染。 store中的状态不允许被直接修改&#xff0c;改变sto…

java进阶学习脑图

今天开始分享我的第一篇博客&#xff0c;先放上我自己花费一个月完成的java进阶学习脑图吧&#xff01; 谁都想像R大一样对JVM可以知无不言&#xff0c;言无不尽&#xff1b; 谁都想像Doug Lea一样可以参与JUC这种核心模块的开发&#xff1b; 但是&#xff0c;不能只停留在想…

【设计师专属】智能屏幕取色器Pro|RGB/HEX双模式|快捷键秒存|支持导出文档|C++ QT

&#x1f525; “1秒锁定千万色值&#xff0c;让灵感不再流失&#xff01;” ✔ 像素级精准捕捉 ✔ 快捷键极速记录 ✔ 数据一键导出 ✔ 开发者/设计师效率神器 "还在手动截图比色&#xff1f;加班改稿只因色差&#xff1f;前端还原总被吐槽&#xff1f; &#x1f449;…

力扣 下一个排列

交换位置&#xff0c;双指针&#xff0c;排序。 题目 下一个排列即在组成的排列中的下一个大的数&#xff0c;然后当这个排列为降序时即这个排列最大&#xff0c;因为大的数在前面&#xff0c;降序排列的下一个数即升序。所以&#xff0c;要是想找到当前排列的下一个排列&…

在 HuggingFace 中使用 SSH 进行下载数据集和模型

SSH 是一种 安全通讯的协议&#xff0c;我们通过配置 SSH 的密钥 来在 Git 上实现 Huggingface 模型的命令行下载。 参考网址&#xff1a;https://huggingface.co/docs/hub/security-git-ssh 点击自己的头像&#xff0c;点击 Add SSH key 在 Windows 上&#xff0c;我们实现已…

【生成模型】【ComfyUI(三)】使用WebAPI批量调用ComfyUI

可以参考【生成模型】【ComfyUI&#xff08;一&#xff09;】Flux与Flux-Fill部署与API调用中Flux-Fill部分 1. 调整Workflow 我们要部署以下workflow 做两个修改 输入改为从Load Image(Base64) 读入图片&#xff0c;当然使用上面的从路径中读图也是可以的输出改为SaveImag…

【多模态大模型】端侧语音大模型minicpm-o:手机上的 GPT-4o 级多模态大模型

MiniCPM-o ,它是一款 开源、轻量级 的多模态大语言模型,目标是在手机等资源受限的环境中实现 GPT-4o 级别的多模态能力! 1. MiniCPM-o:小身材,大能量! MiniCPM-o 的名字已经暗示了它的核心特点:Mini (小巧) 和 CPM (中文预训练模型),最后的 “o” 则代表 Omnimodal …

【C++】深入理解List:双向链表的应用

凭时间赢来的东西&#xff0c;时间肯定会为之作证。 前言 这是我自己学习C的第七篇博客总结。后期我会继续把C学习笔记开源至博客上。 上一期笔记是关于C的vector类知识&#xff0c;没看的同学可以过去看看&#xff1a;【C】探索Vector&#xff1a;灵活的数据存储解决方案-CS…

Spring Cloud源码 - Eureka源码原理分析

Eureka源码原理分析 文章目录 Eureka源码原理分析一&#xff1a;启动过程源码1&#xff1a;初始化环境2&#xff1a;初始化上下文2.1&#xff1a;加载erueka-server配置文件2.2&#xff1a;构造实例信息管理器2.3&#xff1a;初始化erueka-client2.4&#xff1a;处理注册相关的…

2.23操作列表

操作列表 一&#xff1a;遍历整个列表 – for循环 names[xixi, gofy, haha] for name in names:print(f"{name} is very very good good")print(f"{name}&#xff0c;欢迎回家\n")xixi is very very good good xixi&#xff0c;欢迎回家gofy is very ver…

Solidity study

Solidity 开发环境 Solidity编辑器&#xff1a;Solidity编辑器是一种专门用于编写和编辑Solidity代码的编辑器。常用的Solidity编辑器包括Visual Studio Code、Atom和Sublime Text。以太坊开发环境&#xff1a;以太坊开发环境&#xff08;Ethereum Development Environment&am…

Git版本控制系统---本地操作(万字详解!)

目录 git基本配置 认识工作区、暂存区、版本库 添加文件--情况一&#xff1a; 添加文件-情况二: 修改文件: 版本回退&#xff1a; git基本配置 1.初始化本地仓库&#xff0c;注意&#xff1a;一定要在一个目录下进行&#xff0c;一般都是新建一个文件夹&#xff0c;在文件…

IDEA配置JSP环境

首先下载IDEA2021.3&#xff0c;因为最新版本不能简单配置web开发环境。然后新建一个java开发项目&#xff1a; 然后右键创建的项目&#xff0c;添加web框架&#xff1a; 选择web appliciation 在web inf文件夹下创建classes和lib文件夹&#xff1a; 点击file &#xff0c;选择…

前端兼容处理接口返回的文件流或json数据

参考文档&#xff1a;JavaScript | MDN 参考链接&#xff1a;Blob格式转json格式&#xff0c;拿到后端返回的json数据_blob转json-CSDN博客 参考链接&#xff1a;https://juejin.cn/post/7117939029567340557 场景&#xff1a;导入上传文件&#xff0c;导入成功&#xff0c;…

短剧源码部署搭建小程序搭建IAA+IAP混合解锁模式

在当今数字化内容消费迅速增长的时代&#xff0c;短剧作为一种新兴的内容形式&#xff0c;凭借其短小精悍、节奏紧凑的特点&#xff0c;迅速吸引了大量用户。作为一名软件体验测试人员&#xff0c;我有幸体验了一款集创新与实用为一体的短剧小程序。这款小程序不仅在前端用户体…

网络原理---HTTP/HTTPS

通过之前的网络编程&#xff0c;我们已经初步了解UDP和TCP的基本实现方法&#xff0c;接下来我们对其进一步的学习。 在网络编程中&#xff1a; 1.读和写数据通过Socket&#xff0c;通过Socket内置的InputStream和OutputStream(读写的基本单位都是字节&#xff09;。2.当在编…

【Python修仙编程】(二) Python3灵源初探(2)

第一部分&#xff1a;林羽的修仙之旅——字符串与布尔类型的修炼 林羽站在练气期一阶的起点&#xff0c;望着手中的《Python无极心法》秘籍&#xff0c;心中充满了期待。师傅玄天真人在一旁微笑着说道&#xff1a;“林羽&#xff0c;今天我们要修炼的是‘字符串’和‘布尔类型…

【HTML— 快速入门】HTML 基础

准备工作 vscode下载 百度网盘 Subline Text 下载 Sublime Text下载 百度网盘 vscode 下载 Sublime Text 是一款轻量好用的文本编辑器&#xff0c;我们在写前端代码时&#xff0c;使用 Sublime Text 打开比使用记事本打开&#xff0c;得到的代码体验更好&#xff0c;比 vscode…

pipeline 使用git parameter插件实现动态选择分支构造

效果&#xff0c;&#xff0c;点击build with Parameters 就会出现右边的当前仓库的所有的分支&#xff0c;默认最多显示5个&#xff0c;可以修改配置&#xff0c;修改显示的最大分支数量。如果分支太多&#xff0c;可以通过右边的过滤框输入过滤。 安装git params插件 搜索g…

国产OS上完整编译Qt5.15、搭建基本开发环境需要的库

近期有师弟问我国产OS安装Qt5.15编译老是不完整&#xff0c;不是没声音&#xff0c;就是没视频&#xff0c;或者没有xcb。通过QEMU模拟Arm64&#xff0c;闲来20几天摸索&#xff0c;完整编译了Qt5.15&#xff0c;并编译成功了我的SDR玩具taskBus。 1.主要结论&#xff1a; 该O…