当前位置: 首页 > article >正文

鸿蒙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


http://www.kler.cn/a/561821.html

相关文章:

  • 【Redis 原理】网络模型
  • 社群团购平台的愿景构建与开源链动2+1模式S2B2C商城小程序应用探索
  • vscode多文件编译构建(CMake)和调试C++
  • 系统思考:第五项修炼
  • Transceivers Wizard IP核
  • zookeeper 客户端常用命令
  • 8. 示例:对32位数据总线实现位宽和值域覆盖
  • 5. grafana的Graph panel使用
  • C 语言中控制文件的读取或写入光标
  • P8772 [蓝桥杯 2022 省 A] 求和--简单题的陷阱——(不开long long见祖宗!!!
  • ElasticSearch公共方法封装
  • Django 视图函数中的 `response` 对象及类型扩写
  • 基于SpringBoot实现的宠物领养系统平台功能十一
  • 校园的网络安全
  • 策略模式在工作中的运用
  • 渗透测试实验
  • 【算法】 ‘abb‘ 型子序列问题——前后缀分解 python
  • Spark on Yarn 多机集群部署
  • RBAC授权
  • 【透视图像目标检测(4)】DD3D输出3D障碍物信息的过程