鸿蒙ArkUI体验:Hexo博客客户端开发心得


最近部门也在跟进鸿蒙平台的业务开发,自己主要是做 Android 开发,主要使用 Kotlin/Java 语言。,需要对新的开发平台和开发模式进行学习,在业余时间开了个项目练手,做了个基于 Hexo 博客内容开发的App。鸿蒙主要使用ArkTS语言和ArkUI框架进行开发,有使用 Jetpack Compose 和 JavaScript/TypeScript 的开发经验的话,上手会比较的轻松。本文主要介绍做的App功能以及对鸿蒙开发体验的一个总结。

App 简介

后台数据来自 Hexo 生成的博客文章,利用 hexo-generator-wxapi 生成 api .json 文件,再利用 七牛云 提供对图片和 .json 文件 CDN。

实现的功能

  • 博客列表分页加载
  • 文章详情加载
  • 文章按分类/标签展示
  • 文章内容统计
  • 深色/浅色模式切换
  • 数据本地缓存

功能预览

博客列表统计个人文章详情分类标签

依赖项

Hexo
  • Hexo 快速、简洁且高效的博客框架
  • hexo-generator-wxapi 用于将 Hexo 博客内容生成 api 风格的.json文件
  • 七牛云 提供对图片和.json文件 CDN加速
HarmonyOS
  • ArkTS ArkTS在TypeScript(简称TS)生态基础上做了进一步扩展,保持了TS的基本风格,同时通过规范定义强化开发期静态检查和分析,提升代码健壮性,并实现更好的程序执行稳定性和性能。
  • ArkUI ArkUI(方舟UI框架)为应用的UI开发提供了完整的基础设施,包括简洁的UI语法、丰富的UI功能(组件、布局、动画以及交互事件),以及实时界面预览工具等,可以支持开发者进行可视化界面开发。
  • ohos_pull_to_refresh 列表加载/刷新控件(没有’No more’的状态)
  • MMKV 是基于 mmap 内存映射的 key-value 组件

鸿蒙开发总结

ArkTs 语言

ArkTS 是 TypeScript 的超集,TypeScript 又是 JavaScript 的超集,所以对于基本数据类型使用的是 TypeScript 语法。他们三者的关系如下图所示:

相关的差异可以参考社区话题讨论 ArkTS与Typescript的区别?
上图也来自这里的讨论。

这里主要记录一下自己使用过程中踩过的坑:

基本语言类型

Number 和 number 是两个不同的类型,Number 是 JavaScript 中的一个全局对象,可以使用 new Number() 来创建一个 Number 对象。同理对于 String 和 string,Boolean 和 boolean 也是一样的,大写开头的是包装对象类型,小写的是原始类型,这点Java/kotlin也有类似的包装对象比较好理解,但 Object 居然也有大小写之区分相比难理解点,写代码的时候好几次忽略了这个事,Object 是所有对象的基类,object 表示非原始类型(即不是 number、string、boolean、symbol、null 或 undefined 的所有类型)。可以是任何对象、数组、函数、类实例等。

let obj: object;
obj = { a: 1 };         // ✅ 正确:普通对象
obj = [1, 2, 3];        // ✅ 正确:数组
obj = () => {};         // ✅ 正确:函数
obj = new Date();       // ✅ 正确:类实例obj = 42;               // ❌ 错误:原始类型 number
obj = "hello";          // ❌ 错误:原始类型 string

两则的区别

特性objectObject
允许的值仅非原始类型(对象、数组等)任意类型(包括原始值)
原始值处理禁止自动装箱(如 42 → Number)
使用场景明确限制为非原始类型时极少使用(通常用 unknown 或具体类型替代)
Map 等集合类当作普通 JavaScript 对象来操作
let map = new Map<string, object>();
map["key"] = value;            // ❌ 错误用法!
console.log(map.get("biz"));   // ❌ 输出 undefined

最开始挺奇怪的 map 明明设置了值,但是对应的 map size 为0,遍历 map 也没有数据。后来才发现是这种方式 不会 触发 Map 的内部机制,而是绕过了 Map 的方法,直接操作对象的属性,赋值后,键值对 不会 被存入 Map 的真实存储中,而是作为对象的普通属性存在。正确的用法是:

let map = new Map<string, object>();
map.set["key"] = value;        //  ✅ 正确用法!
console.log(map.get("biz"));   //  ✅ 输出 value
struct 的困扰

在 js 里面是没有 struct 这个关键词的,从刚接触到现在它唯一的作用就是:和 @Component绑定声明一个UI控件。例如:

@Component
export struct ToolBar{}

@Componentstruct 两则缺一不可,既然必须有 @Component来标注这是一个UI控件,为什么不能下面这样呢?能省掉一个关键字。

@Component
export class ToolBar {}

同样困扰的人还有很多,这里有一份讨论定义组件时的stuct关键字是什么?
官方也有一份聊胜于无的介绍

struct和class的区别是什么?

struct只在自定义组件中使用,@Component装饰的struct就是自定义组件,自定义组件和class是两个概念,自定义组件没有类型,也不能等同于class。如果开发者需要使用组件作为参数在组件之间传递,可以使用自定义占位节点。

我猜测这样是为了省掉对@Component装饰器编译的工作量,如果使用 class 声明,那么声明的UI控件就有“面向对象”的能力,实际上只希望它是一个UI控件声明,不需要它有其他的能力。难道不能对 @Component 装饰过的对象收回“面向对象”的能力么?当然能啊,估计要做很多编译检查的事儿。另外,从开发理解的层面上来讲,它确实也已经不是"对象"了,它只是一个干巴巴的一个UI结构,所以干脆就搞了一个新的关键词 struct。

ArkUI 框架

整体框架使用的方式和 Jetpack Compose 类似,都是声明式UI框架。compose 里面使用 @Composable来标记某个方法这个方法便成了UI控件,控件里面的状态管理使用 remember+ mutableState来控制。而 ArkUI 通过 @State、@Link、@Prop 等装饰器来控制。了解了这些个装饰器的用法,基本上就能理解 ArkUI 的开发流程了。

构建 UI 的 @Component @Builder

@Component 和 @Builder 组合起来实现的差不多就是 Compose 里面使用 @Composable 装饰某个方法的作用,用于构建 UI 或可复用的逻辑单元。
@Component
用于创建一个自定义组件,组件可以包含独立的 UI 结构、状态管理和生命周期。

@Builder
定义可复用的 UI 片段,用于创建一个UI 构建函数,封装一段可复用的 UI 代码块。不是独立组件,而是嵌入到其他组件或布局中执行,主要作用是复用和逻辑隔离,例如:关于页面,里面的文本是差不多的样式,只是内容不一样,那么只需要保留一个 text 属性出来接收参数。或者某块UI比较复杂,可以抽离一部分UI成为一个独立的UI逻辑模块。

构建 UI 的状态控制装饰器

@State
比较常用的装饰器,和 Compose 里面 remember+mutableStateOf 的作用差不多,对应的值改变之后,对相关的使用到该属性UI的地方进行刷新。

@Prop
@Prop 装饰的变量和父组件建立单向的同步关系,@Prop变量允许在本地修改,但修改后的变化不会同步回父组件。

也就是在某个 @Component 的组件内有一个 @State 装饰的属性,传递到子 @Component 组件 @Prop 修饰的属性。子控件对这个属性修改之后,父控件不会对这个改变感知,父控件UI不会改变。

@Link
子组件中被@Link装饰的变量与其父组件中对应的数据源建立双向数据绑定。
跟 @Prop 的作用类似,不过是双向的,子控件对这个属性修改之后,父控件会感知这个变化,父控件UI会随着这个属性改变而改变。

@BuilderParam
主要用于动态注入 UI 构建逻辑(即 @Builder 函数),实现父组件向子组件传递可定制的 UI 片段,也就是向子控件传递 UI 参数。

基本上比较常用到的就这些,还有很多例如:@LocalBuilder @StorageLink @Styles等,都是为了解决开发过过程中遇到的问题,但是只要掌握了 ArkUI UI组件的声明周期和状态管理的基本原理理解其他装饰器还是比较简单的。

总结

总体开发体验下来,鸿蒙开发学习成本并不是特别高,比较快能上手,但设计的 api 更像一个缝合怪,且使用上不太收敛。很多库还需要再建设,例如音视频开发对应的支持库还不是特别成熟。不过,作为一个从头搞的生态来说能实现成这样已经很不错了,就像此前武磊登陆西甲,以及目前被看好的青年新星王钰栋,都是"自己的孩子",需要迈出第一步。现在,很多公司也在适配鸿蒙了,期待未来能从 Android 跟 iOS 的生态中争夺出一片大市场。

工程相关源码:
blog_harmony

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

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

相关文章

【和春笋一起学C++】(十四)指针与const

将const用于指针&#xff0c;有两种情况&#xff1a; const int *pt; int * const pt; 目录 1. const int *pt 2. int * const pt 3. 扩展 1. const int *pt 首先看第一种情况&#xff0c;const在int的前面&#xff0c;有如下语句&#xff1a; int peoples12&#xff1…

本地缓存更新方案探索

文章目录 本地缓存更新方案探索1 背景2 方案探索2.1 初始化2.2 实时更新2.2.1 长轮询2.2.1.1 client2.2.2.2 server 本地缓存更新方案探索 1 背景 大家在工作中是否遇到过某些业务数据需要频繁使用&#xff0c;但是数据量不大的情况&#xff0c;一般就是几十条甚至几百条这种…

深入理解 requestIdleCallback:浏览器空闲时段的性能优化利器

requestIdleCallback 核心作用 requestIdleCallback 是浏览器提供的 API&#xff0c;用于将非关键任务延迟到浏览器空闲时段执行&#xff0c;避免阻塞用户交互、动画等关键任务&#xff0c;从而提升页面性能体验。 基本语法 const handle window.requestIdleCallback(callb…

51单片机——交通指示灯控制器设计

设计目标 1、设计一交通灯控制&#xff0c;控制东西方向的红、黄、绿灯和南北方向的红、黄、绿灯。 2、可手动控制和自动控制&#xff0c;设置两个输入控制开关。 手动/自动开关&#xff0c;通过P11的按键输入控制 3、手动&#xff1a;设置开关P11&#xff0c;两种情况&#x…

神经网络语言模型(前馈神经网络语言模型)

神经网络语言模型 什么是神经网络&#xff1f;神经网络的基本结构是什么&#xff1f;输入层隐藏层输出层 神经网络为什么能解决问题&#xff1f;通用近似定理为什么需要权重和偏置&#xff1f;为什么需要激活函数&#xff1f;权重是如何确定的&#xff1f;1. 穷举2. 反向传播主…

信息系统项目管理师高级-软考高项案例分析备考指南(2023年案例分析)

个人笔记整理---仅供参考 计算题 案例分析里的计算题就是进度、挣值分析、预测技术。主要考査的知识点有:找关键路径、求总工期、自由时差、总时差、进度压缩资源平滑、挣值计算、预测计算。计算题是一定要拿下的&#xff0c;做计算题要保持头脑清晰&#xff0c;认真读题把PV、…

unordered_map和unordered的介绍和使用

目录 unordered系列关联式容器 unordered_map unordered_map的接口说明 unordered_map的定义方式 unordered_map接口的使用 unordered_map的容量 unordered_map的迭代器 unordered_map的元素访问 unordered_map的查询 unordered_map的修改操作 unordered_multimap u…

设计模式7大原则与UML类图详解

设计模式7大原则与UML类图详解 引言 &#x1f31f; 在软件工程领域&#xff0c;设计模式和UML&#xff08;统一建模语言&#xff09;是提高代码质量、增强系统可维护性的重要工具。设计模式提供了解决软件设计中常见问题的通用方案&#xff0c;而UML则为我们提供了一种可视化的…

计算机视觉与深度学习 | Python实现ARIMA-LSTM时间序列预测(完整源码和数据)

ARIMA-LSTM混合模型 1. 环境准备2. 数据生成(示例数据)3. 数据预处理4. ARIMA建模5. LSTM残差建模6. 混合预测7. 结果可视化完整代码说明1. **数据生成**2. **ARIMA建模**3. **LSTM残差建模**4. **混合预测**5. **性能评估**参数调优建议扩展方向典型输出以下是使用Python实现…

Docker部署单节点Elasticsearch

1.Docker部署单节点ES 1.前置条件 配置内核参数 echo "vm.max_map_count262144" >> /etc/sysctl.conf sysctl -w vm.max_map_count262144准备密码 本文所有涉及密码的配置&#xff0c;均使用通用密码 Zzwl2024。 生产环境&#xff0c;请用密码生成器生成20…

pe文件二进制解析(用c/c++解析一个二进制pe文件)

pe文件二进制解析 c解析pe文件控制台版本 #include<iostream> #include<windows.h> #include<vector>/*RVA&#xff08;相对虚拟地址&#xff09;与FOA&#xff08;文件偏移地址&#xff09;的转换1.得到 的值&#xff1a;内存地址 - ImageBase2.判断是否位…

融智学视域下的系统性认知增强框架——基于文理工三类AI助理赋能HI四阶跃迁路径

融智学视域下的系统性认知增强框架 ——基于文理工三类AI助理赋能HI四阶跃迁路径 一、如何排除50个认知偏差&#xff1a;消除50类偏差的精准矫正系统 1. 技术架构 文科AI&#xff1a; 构建文化语义场&#xff08;Cultural Semantic Field, CSF&#xff09;&#xff0c;通过…

MMDetection环境安装配置

MMDetection 支持在 Linux&#xff0c;Windows 和 macOS 上运行。它需要 Python 3.7 以上&#xff0c;CUDA 9.2 以上和 PyTorch 1.8 及其以上。 MMDetection 至今也一直更新很多个版本了&#xff0c;但是对于最新的pytorch版本仍然不支持&#xff0c;我安装的时候仍然多次遇到m…

如何实现k8s高可用

一、控制平面高可用设计 多主节点部署 • API Server 冗余&#xff1a;部署至少 3 个 Master 节点&#xff0c;每个节点运行独立的 API Server&#xff0c;通过负载均衡器&#xff08;如 Nginx、HAProxy、云厂商 LB&#xff09;对外提供统一入口。 • 选举机制&#xff1a;Sche…

记录心态和工作变化

忙中带闲的工作 其实工作挺忙的, 总是在赶各种功能点. 好巧的是iOS那边因为上架的问题耽搁了一些时间, 从而让Android的进度有了很大的调整空间. 更巧的是后端那边因为对客户端的需求不是很熟悉, 加上Android海外这块的业务他也是第一次接触. 所以需要给他留一些时间把各个环节…

JVM 双亲委派机制

一、从 JDK 到 JVM&#xff1a;Java 运行环境的基石 在 Java 开发领域&#xff0c;JDK&#xff08;Java Development Kit&#xff09;是开发者的核心工具包。它不仅包含了编译 Java 代码的工具&#xff08;如 javac&#xff09;&#xff0c;还内置了 JRE&#xff08;Java Run…

java开发之异常

一 结构 Throwable分为Exception和error Exception分为RuntimeException&#xff08;运行时异常&#xff09;和其他异常 主动抛出运行时异常和非运行时异常的区别 1、throw RuntimeException&#xff08;或运行时异常的子类&#xff09; 编译时不会报错。 2、throw Excepti…

MySQL 中 JOIN 和子查询的区别与使用场景

目录 一、JOIN:表连接1.1 INNER JOIN:内连接1.2 LEFT JOIN:左连接1.3 RIGHT JOIN:右连接1.4 FULL JOIN:全连接二、子查询:嵌套查询2.1 WHERE 子句中的子查询2.2 FROM 子句中的子查询2.3 SELECT 子句中的子查询三、JOIN 和子查询的区别3.1 功能差异3.2 性能差异3.3 使用场…

2025年第三届盘古石杯初赛(智能冰箱,监控部分)

前言 所以去哪里可以取到自己家里的智能家居数据呢&#xff1f;&#xff1f;&#xff1f;&#xff1f; IOT物联网取证 1、分析冰箱&#xff0c;请问智能冰箱的品牌&#xff1f; [答案格式&#xff1a;xiaomi] Panasonic2、请问智能冰箱的型号&#xff1f; [答案格式&#x…

【强化学习】强化学习算法 - 马尔可夫决策过程

文章目录 马尔可夫决策过程 (Markov Decision Process, MDP)1. MDP 原理介绍2. MDP 建模/实现步骤3. MDP 示例&#xff1a;简单网格世界 (Grid World) 马尔可夫决策过程 (Markov Decision Process, MDP) 1. MDP 原理介绍 马尔可夫决策过程 (MDP) 是强化学习 (Reinforcement L…