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;// 需要绑定的组件的IDbindId?: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.mzph.cn/pingmian/53708.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

四款音频剪辑软件免费使用,你更pick哪一个?

视频剪辑知随着软件的不断更新,入门门槛和操作难度也随之变得越来越低,但是依然有不少人不知道剪辑视频要用什么工具,作为一个视频剪辑爱好者,我尝试过不少编辑软件,今天就来跟大家分享一下四款视频剪辑软件在实际使用…

通用四期ARM架构银河麒麟桌面操作系统V10【安装、配置FTP客户端】

一、操作环境 服务端:银河麒麟桌面操作系统V10SP1 客户端:银河麒麟桌面操作系统V10SP1 二、服务端配置 注:以下命令均在终端执行 鼠标点击桌面右键,选择打开终端 操作步骤: 1、安装vsftpd软件:如果提…

深入理解TCP三次握手

在网络通信中,TCP(Transmission Control Protocol,传输控制协议)是一个可靠的、面向连接的协议,它保证了数据包的顺序和完整性。为了建立一个稳定的连接,TCP 使用了一个被称为 三次握手(Three-W…

滑动窗口(1)_长度最小的子数组

个人主页:C忠实粉丝 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C忠实粉丝 原创 滑动窗口(1)_长度最小的子数组 收录于专栏【经典算法练习】 本专栏旨在分享学习C的一点学习笔记,欢迎大家在评论区交流讨论💌 目录 1. …

一款高效、简洁的帧动画生成工具

在现代网页设计和移动应用开发中,帧动画是一种常见的动画实现方式,它通过连续显示一系列静态图片来模拟动画效果。然而,手动创建和管理这些帧动画图片不仅耗时费力,而且效率低下。为此,gka 应运而生,它是一…

Java学习Day41:骑龙救!(springMVC)

springMVC与sevlet都是对应表现层web的,但是越复杂的项目使用SpringMVC越方便 基于Java实现MVC模型的轻量级web框架 目标: 小案例: 1.导入依赖 spring-context: 提供 Spring 框架的核心功能,如依赖注入、事件发布和其他应用上…

无人机之伯努利定律

无人机的伯努利定律是解释无人机飞行原理的关键理论之一,它主要阐述了流体(如空气)在流动过程中速度与压力之间的关系。以下是对无人机伯努利定律的详细解释: 一、伯努利定律的基本原理 伯努利定律是流体力学中的一个基本原理&am…

【python】—— Python爬虫实战:爬取珠海市2011-2023年天气数据并保存为CSV文件

目录 目标 准备工作 爬取数据的开始时间和结束时间 爬取数据并解析 将数据转换为DataFrame并保存为CSV文件 本文将介绍如何使用Python编写一个简单的爬虫程序,以爬取珠海市2011年至2023年的天气数据,并将这些数据保存为CSV文件。我们将涉及到以下知识点: 使用r…

Word 脚注与正文之间的空行怎么删除啊?

全网都搜索不到解决方案,难道只有我一个人遇到这个问题了吗? 无语,。、;

Java导入、导出excel保姆级教程(附封装好的工具类)

前言 我们在日常开发中,一定遇到过要将数据导出为Excel的需求,那么怎么做呢?在做之前,我们需要思考下Excel的组成。Excel是由四个元素组成的分别是:WorkBook(工作簿)、Sheet(工作表)、Row(行)、Cell(单元格)&#xff…

linux入门到实操-1 Linux概述、诞生过程、发行版本,如何安装?

教程来源:B站视频BV1WY4y1H7d3 3天搞定Linux,1天搞定Shell,清华学神带你通关_哔哩哔哩_bilibili 整理汇总的课程内容笔记和课程资料,供大家学习交流下载:夸克网盘分享 本文内容为完整笔记的入门篇 概述部分历史内容…

使用LSTM(长短期记忆网络)模型预测股票价格的实例分析

一:LSTM与RNN的区别 LSTM(Long Short-Term Memory)是一种特殊的循环神经网络(RNN)架构。LSTM是为了解决传统RNN在处理长序列数据时遇到的梯度消失或梯度爆炸问题而设计的。 在传统的RNN中,信息通过隐藏状…

使用虚拟信用卡WildCard轻松订阅POE:全面解析平台功能与订阅方式

POE(Platform of Engagement)是一个由Quora推出的人工智能聊天平台,汇集了多个强大的AI聊天机器人,如GPT-4、Claude、Sage等。POE提供了一个简洁、统一的界面,让用户能够便捷地与不同的AI聊天模型进行互动。这种平台的…

基于SpringBoot的社团管理系统

作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 基于JavaSpringBootVueMySQL的社团管理系统【附源码文档】、…

HashTable哈希表

概念 散列表(Hash Table),又称哈希表。是一种数据结构,特点是:数据元素的关键字与其存储地址直接相关 在顺序结构以及树型结构中,数据元素的关键字与其存储位置没有对应的关系,因此在查找一个元素时,必须要经过关键码…

Windows 平台安装 Nacos 2.x

环境准备 64 位操作系统,Windows 10 / Linux Centos 7JDK 1.8 安装包下载 安装包下载官方地址:https://github.com/alibaba/nacos/releases 启动 将安装包解压到安装的目录下,改名为 nacos-2.0.4。然后进行到 bin 目录下,打开…

软件测试服务公司出具第三方软件测试报告流程和周期简析

随着信息技术的飞速发展,软件已成为各行各业不可或缺的重要工具。然而,软件的质量直接影响到企业的效率和用户体验,因此,软件测试服务的重要性日益凸显。软件测试服务公司,顾名思义,就是专门提供专业的软件…

工业机器人9公里远距离图传模块,无人机低延迟高清视界,跨过距离限制

在科技日新月异的今天,无线通信技术正以未有的速度发展,其中,图传模块作为连接现实与数字世界的桥梁,正逐步展现出其巨大的潜力和应用价值。今天,我们将聚焦一款引人注目的产品——飞睿智能9公里远距离图传模块&#x…

LiveKit的agent介绍

概念 LiveKit核心概念: Room(房间)Participant(参会人)Track(信息流追踪) Agent 架构图 ​ 订阅信息流 ​ agent交互流程 客户端操作 加入房间 房间创建方式 手动 赋予用户创建房间的…

JavaScript - Api学习 Day03 (日期对象、节点操作、两种定时器、本地存储)

文章目录 一、日期对象1.1 实例化1.2 日期对象方法 二、节点操作2.1 父子兄弟节点1. 父节点查找2. 子节点查找3. 兄弟关系查找 2.2 增删节点1. 创建节点 - createElement2. 添加节点2.1 appendChild() 方法2.2 insertBefore() 方法2.3. 克隆节点 - cloneNode 3. 删除节点3.1 re…