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

HarmonyOS开发实战( Beta5.0)自定义装饰器实践规范

介绍

本示例介绍通过自定义装饰器在自定义组件中自动添加inspector (布局回调)方法并进行调用。

效果图预览

不涉及

使用说明

  1. 在自定义组件上添加自定义装饰器@CallbackObserver,并根据参数设置对应的方法名和需要绑定的组件的ID。
  2. 编译工程,可以根据自定义装饰器生成方法并调用。
具体使用方法
  1. 在工程的hvigor-config.json5中配置插件。

    {
      ...
      "dependencies": {
        ...
        "@app/ets-decoration": "file:../libs/autobuilddecoration-1.0.0.tgz"
      }
    }
    
  2. 在需要使用自定义装饰器的模块的hvigorfile.ts中添加依赖和文件路径。

    import { harTasks } from '@ohos/hvigor-ohos-plugin';
    import { DecorationPluginConfig, etsDecorationPlugin } from '@app/ets-decoration';
    
    const config: PluginConfig = {
      scanFiles: [""],
    }
    export default {
      system: harTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
      plugins: [etsDecorationPlugin(config)]         /* Custom plugin to extend the functionality of Hvigor. */
    }
    
  3. 在自定义组件上添加自定义装饰器@CallbackObserver,并设置对应的方法名和组件ID。

    @CallbackObserver({
     onDraw: 'onDraw',
     onLayout: 'onLayout',
     offDraw: 'offDraw',
     offLayout: 'offLayout',
     bindId: 'text'
    })
    @Component
    export struct MainPage {
     build() {
       Column() {
         Text("Hello World")
           .id('text')
       }
     }
    }
    
  4. 编译工程,即可生成对应的方法和调用代码。

实现思路

  1. 在ArkTS侧实现自定义装饰器,并配置需要的参数。

    // 自定义装饰器
    export function AutoAddInspector(param: InspectorParam) {
      return Object;
    }
    // 装饰器参数
    export interface InspectorParam {
      // inspector中onDraw需要配置的回调方法
      onDraw?: string;
      // inspector中onLayout需要配置的回调方法
      onLayout?: string;
      // inspector中offDraw需要配置的回调方法
      offDraw?: string;
      // inspector中offLayout需要配置的回调方法
      offLayout?: string;
      // 需要绑定的组件的ID
      bindId?:string;
    }
    
  2. 通过hvigorfile.ts中的配置,将使用自定义装饰器的文件路径传到插件中。

    import { DecorationPluginConfig, etsDecorationPlugin } from '@app/ets-decoration-generator';
    
    const config: DecorationPluginConfig = {
    	// 配置自定义装饰器的文件路径
        scanFiles: ["src/main/ets/components/MainPage"],
    }
    
    export default {
        system: harTasks,  /* Built-in plugin of Hvigor. It cannot be modified. */
        plugins:[etsDecorationPlugin(config)]         /* Custom plugin to extend the functionality of Hvigor. */
    }
    
  3. 将传入的文件解析为TypeScript抽象语法树,得到所有的节点信息。详细代码可参考Index.ts。

    start() {
      // 读取文件
      const sourceCode = readFileSync(this.sourcePath, "utf-8");
      // 解析文件,生成节点树信息
      const sourceFile = ts.createSourceFile(this.sourcePath, sourceCode, ts.ScriptTarget.ES2021, false);
      // 遍历节点信息
      ts.forEachChild(sourceFile, (node: ts.Node) => {
        // 解析节点
        console.log(JSON.stringify(node));
        this.resolveNode(node);
      });
    }
    
  4. 遍历节点,获取自定义装饰器中配置的参数,将方法名存入到列表中。

    // 解析装饰器
    resolveDecoration(node: ts.Node) {
      ...
      if ((propertie.name as ts.StringLiteral).text !== 'bindId') {
        // 如果参数名不是“bindId”,则放入需要创建的方法列表中
        let methodInfo: MethodInfo = new MethodInfo();
        methodInfo.name = (propertie.name as ts.StringLiteral).text;
        methodInfo.value = (propertie.initializer as ts.StringLiteral).text;
        decoratorInfo.methods.push(methodInfo);
        this.methodArray.push((propertie.initializer as ts.StringLiteral).text);
      } else {
        // 如果参数名是“buildId”,则设置到对应的变量中
        decoratorInfo.bindId = (propertie.initializer as ts.StringLiteral).text;
      }
      ...
      this.decorationInfos.push(decoratorInfo);
      ...      
    }
    
  5. 遍历节点,记录aboutToAppear()方法的位置,并和第4步中存储的列表进行比较,过滤已经存在的方法,防止生成同名方法。

    // 解析装饰器装饰的自定义组件(从“{”到“}”)
    resolveBlock(node: ts.Node) {
      ...
      // 自定义组件中已经存在的方法列表
      const methodNameArray: string[] = [];
      statements.forEach((statement: ts.Statement) => {
        ...
        const identifier = callExpression.expression as Identifier;
        methodNameArray.push(identifier.escapedText.toString());
        // 查找是否已经存在aboutToAppear方法
        if (identifier.escapedText === 'aboutToAppear') {
          this.aboutToAppearExist = true;
          this.positionOfAboutToAppear = statement.pos;
        }
        ...
      })
      // 过滤已经存在的装饰器中的方法
      const temp = this.methodArray.filter((value: string, index: number) => {
        return !methodNameArray.includes(value);
      })
      this.methodArray = temp;
      // 记录自定义组件的结束位置
      this.positionOfBlockEnd = node.end;
      }
    }
    
  6. 根据解析结果,生成方法代码和相关调用代码,并写入原文件中。

    function pluginExec(config: DecorationPluginConfig) {
      ...
      // 开始解析文件
      analyzer.start();
      // 如果解析的文件中存在装饰器,则将结果保存到列表中
      if (analyzer.routerAnnotationExisted) {
        // 如果有需要创建的方法
        if (analyzer.methodArray.length > 0) {
          ...
          // 装饰器中如果设置了bindId,则添加listener变量,并在aboutToAppear中调用监听方法
          // aboutToAppear方法是否已存在 
          if (analyzer.aboutToAppearExist) {
            // 如果已经存在aboutToAppear,则根据aboutToAppear方法的位置拆分结构体,并将需要生成的代码添加到对应的位置
            ...
          } else {
            // 如果不存在aboutToAppear方法,则创建aboutToAppear方法,并添加调用代码
            ...
          }
          // 根据模板创建装饰器中配置的方法
          ...
          // 将生成的代码写入文件中
          writeFileSync(sourcePath, fileContent, { encoding: "utf8" })
        }
      }
      ...
    }
    

工程结构&模块类型

customdecoration                               // har类型
|---components
|   |---CallbackObserver.ets                   // 自定义装饰器
|   |---MainPage.ets                           // UI页面

最后

小编在之前的鸿蒙系统扫盲中,有很多朋友给我留言,不同的角度的问了一些问题,我明显感觉到一点,那就是许多人参与鸿蒙开发,但是又不知道从哪里下手,因为体系杂乱无章,教授的人也多,无从选择。有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)路线、视频、文档用来跟着学习是非常有必要的。

如果你是一名有经验的资深Android移动开发、Java开发、前端开发、对鸿蒙感兴趣以及转行人员

鸿蒙 NEXT 全栈开发学习笔记 希望这一份鸿蒙学习文档能够给大家带来帮助~


 鸿蒙(HarmonyOS NEXT)最新学习路线

该路线图包含基础技能、就业必备技能、多媒体技术、六大电商APP、进阶高级技能、实战就业级设备开发,不仅补充了华为官网未涉及的解决方案

路线图适合人群:

IT开发人员:想要拓展职业边界
零基础小白:鸿蒙爱好者,希望从0到1学习,增加一项技能。
技术提升/进阶跳槽:发展瓶颈期,提升职场竞争力,快速掌握鸿蒙技术

2.视频教程+学习PDF文档

(鸿蒙语法ArkTS、TypeScript、ArkUI教程……)

 纯血版鸿蒙全套学习文档(面试、文档、全套视频等)

                   

鸿蒙APP开发必备

​​

总结

参与鸿蒙开发,你要先认清适合你的方向,如果是想从事鸿蒙应用开发方向的话,可以参考本文的学习路径,简单来说就是:为了确保高效学习,建议规划清晰的学习路线


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

相关文章:

  • 爬虫补环境案例---问财网(rpc,jsdom,代理,selenium)
  • vscode远程连接服务器并启用tmux挂载进程
  • SpringBoot参数注解
  • SHELL脚本(Linux)
  • influxDB 时序数据库安装 flux语法 restful接口 nodjsAPI
  • 94个属于一区且接受医工交叉领域投稿的期刊汇总|个人观点·24-11-13
  • 【自动驾驶】控制算法(八)横向控制Ⅱ | Carsim 与 Matlab 联合仿真基本操作
  • Android 车联网——汽车系统介绍(附2)
  • Python 课程6-Pandas 和 Matplotlib库
  • MATLAB中的控制系统工具箱:深入指南与实践应用
  • c++ 包装器
  • Git常用命令(记录)
  • 【Android笔记】Android Studio打包 提示Invalid keystore format
  • Cesium 获取BBOX
  • SprinBoot+Vue网络商城海鲜市场的设计与实现
  • uniapp 发布苹果IOS详细流程,包括苹果开发者公司账号申请、IOS证书、.p12证书文件等
  • 【区块链通用服务平台及组件】微言科技数据智能中台
  • [网络]TCP/IP五层协议之应用层,传输层(1)
  • okhttp 报java.lang.IllegalStateException: closed
  • 为什么矩阵特征值之和等于主对角线元素之和,特征值乘积等于行列式值
  • 对话世优科技CEO纪智辉:AI模型让数字人发展按下加速键
  • 基于STM32的汽车仪表显示系统:集成CAN、UART与I2C总线设计流程
  • 【RAG】RAG再进化?基于长期记忆的检索增强生成新范式-MemoRAG
  • 盘古信息IMS 驱动智能工厂建设,助力制造企业降本增效
  • 力扣第79题 单词搜索
  • SprinBoot+Vue门诊管理系统的设计与实现