03 HarmonyOS Next仪表盘案例详解(二):进阶篇
温馨提示:本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦!
文章目录
- 前言
- 1. 响应式设计
- 1.1 屏幕适配
- 1.2 弹性布局
- 2. 数据展示与交互
- 2.1 数据卡片渲染
- 2.2 图表区域
- 3. 事件处理机制
- 3.1 点击事件处理
- 3.2 手势交互
- 4. 性能优化技巧
- 4.1 懒加载与按需渲染
- 4.2 状态管理优化
- 5. 数据流管理
- 5.1 单向数据流
- 5.2 响应式数据绑定
- 6. 最佳实践
- 6.1 组件化开发
- 6.2 样式与逻辑分离
- 7. 总结
前言
关于HarmonyOS NEXT 的仪表盘 从
-
- HarmonyOS应用开发实践与技术解析
-
- HarmonyOS Next仪表盘案例详解(一):基础篇
再到本章节 就已经全部讲完了, 接下来我们先展示一下其运行的效果
- HarmonyOS Next仪表盘案例详解(一):基础篇
首页List
效果演示
1. 响应式设计
1.1 屏幕适配
// 获取屏幕宽度
this.screenWidth = px2vp(AppStorage.Get<number>('windowWidth') || 720)// 根据屏幕宽度决定每行显示的卡片数量
Flex({ wrap: FlexWrap.Wrap, justifyContent: this.screenWidth > 600 ? FlexAlign.Start : FlexAlign.SpaceAround })// 卡片宽度自适应
.width(this.screenWidth > 600 ? '22%' : '45%')
案例中通过检测屏幕宽度实现响应式布局:
- 当屏幕宽度大于600像素时,每行显示4个卡片,宽度为22%
- 当屏幕宽度小于等于600像素时,每行显示2个卡片,宽度为45%
这种响应式设计使应用能够在不同尺寸的设备上提供良好的用户体验。
1.2 弹性布局
Flex({ wrap: FlexWrap.Wrap, justifyContent: this.screenWidth > 600 ? FlexAlign.Start : FlexAlign.SpaceAround })
使用Flex组件的wrap属性实现卡片的自动换行,并根据屏幕宽度动态调整对齐方式:
- 宽屏设备:左对齐(FlexAlign.Start)
- 窄屏设备:均匀分布(FlexAlign.SpaceAround)
2. 数据展示与交互
2.1 数据卡片渲染
ForEach(this.dataCards, (card: DashboardCardItem) => {// 数据卡片Column() {// 卡片标题Text(card.title).fontSize(14).fontColor('#666').margin({bottom: 12})// 数据值和单位Flex({alignItems: ItemAlign.Baseline}) {Text(card.value).fontSize(28).fontWeight(FontWeight.Bold).fontColor(card.color)Text(card.unit).fontSize(14).fontColor(card.color).margin({left: 4})}.margin({bottom: 8})// 趋势指标Text(card.trend).fontSize(14).fontColor(card.trend.includes('+') ? '#2A9D8F' : '#E76F51')}// 卡片样式...
})
使用ForEach循环渲染数据卡片,每个卡片包含标题、数值、单位和趋势指标。根据趋势的正负动态设置颜色:
- 正向趋势(+):绿色(#2A9D8F)
- 负向趋势(-):红色(#E76F51)
2.2 图表区域
// 图表区域(示意)
Column() {Flex({ justifyContent: FlexAlign.SpaceBetween, alignItems: ItemAlign.Center }) {Text('销售趋势分析').fontSize(18).fontWeight(FontWeight.Medium)Flex() {ForEach(['日', '周', '月', '年'], (item: string) => {Text(item).fontSize(14).fontColor(item === '周' ? '#007DFF' : '#666').backgroundColor(item === '周' ? '#E6F1FF' : 'transparent').height(32).width(40).textAlign(TextAlign.Center).borderRadius(16)})}}// ...// 图表占位区域Column() {Text('此处放置销售趋势图表').fontSize(14).fontColor('#999')}// ...
}
图表区域包含标题栏和时间筛选器,通过ForEach循环渲染日、周、月、年四个选项,并高亮显示当前选中的"周"选项。这种设计允许用户快速切换不同时间维度的数据视图。
3. 事件处理机制
3.1 点击事件处理
ForEach(['日', '周', '月', '年'], (item: string) => {Text(item).fontSize(14).fontColor(item === this.timeRange ? '#007DFF' : '#666').backgroundColor(item === this.timeRange ? '#E6F1FF' : 'transparent').height(32).width(40).textAlign(TextAlign.Center).borderRadius(16).onClick(() => {// 更新选中的时间范围this.timeRange = item// 根据新的时间范围更新图表数据this.updateChartData()})
})
通过onClick事件处理器实现交互功能,当用户点击不同的时间选项时:
- 更新当前选中的时间范围状态变量
- 调用更新图表数据的方法,刷新图表显示
3.2 手势交互
// 图表区域手势交互
GestureGroup({// 同时识别多种手势type: GestureType.Parallel,// 手势之间的关系gestures: [PanGesture({ direction: PanDirection.Horizontal }).onActionStart((event: GestureEvent) => {// 记录起始位置this.startX = event.offsetX}).onActionUpdate((event: GestureEvent) => {// 计算拖动距离,更新图表显示范围let offsetX = event.offsetX - this.startXthis.updateChartViewport(offsetX)}),PinchGesture().onActionUpdate((event: GestureEvent) => {// 根据缩放比例调整图表显示范围this.updateChartScale(event.scale)})]
})
实现了两种手势交互:
- 平移手势(PanGesture):允许用户左右滑动查看不同时间段的数据
- 捏合手势(PinchGesture):允许用户通过捏合操作放大或缩小图表视图
4. 性能优化技巧
4.1 懒加载与按需渲染
LazyForEach(this.dataSource, (item: DataItem) => {// 数据项渲染逻辑DataItemComponent({ data: item })
})
使用LazyForEach代替ForEach进行大量数据的渲染,实现按需加载,提高应用性能:
- 只渲染可见区域的数据项
- 当用户滚动时,动态加载新的数据项
- 释放不可见区域的资源
4.2 状态管理优化
// 使用AppStorage全局状态管理
aboutToAppear() {// 订阅全局状态变化this.dashboardDataSubscriber = AppStorage.Subscribe('dashboardData', (data: DashboardData) => {// 仅在数据变化时更新UIif (JSON.stringify(data) !== JSON.stringify(this.localData)) {this.localData = datathis.updateUI()}})
}aboutToDisappear() {// 取消订阅,避免内存泄漏this.dashboardDataSubscriber.unsubscribe()
}
通过状态管理优化提高应用性能:
- 使用AppStorage进行全局状态管理
- 实现数据变化的细粒度检测,避免不必要的UI更新
- 组件销毁时取消订阅,防止内存泄漏
5. 数据流管理
5.1 单向数据流
// 父组件
@State dashboardData: DashboardData = initialDatabuild() {Column() {// 将数据通过属性传递给子组件DataCards({ data: this.dashboardData.cards })ChartSection({ data: this.dashboardData.chartData,// 传递回调函数处理子组件事件onTimeRangeChange: (range) => this.updateTimeRange(range)})}
}// 子组件
@Component
struct DataCards {// 使用@Prop接收父组件传递的数据@Prop data: CardData[]build() {// 渲染逻辑}
}
实现单向数据流模式:
- 父组件维护应用状态
- 通过属性将数据传递给子组件
- 子组件通过回调函数将事件传递给父组件
- 父组件处理事件并更新状态,触发UI更新
5.2 响应式数据绑定
// 定义响应式状态
@State selectedTimeRange: string = '周'
@State chartData: ChartDataPoint[] = []// 计算属性
@Computed get filteredData(): ChartDataPoint[] {return this.chartData.filter(item => {// 根据选中的时间范围过滤数据if (this.selectedTimeRange === '日') {return item.date.startsWith(this.currentDay)} else if (this.selectedTimeRange === '周') {return this.isInCurrentWeek(item.date)}// 其他条件...})
}build() {Column() {// 使用计算属性自动更新UIChartComponent({ data: this.filteredData })}
}
利用ArkTS的响应式特性:
- 使用@State声明响应式状态
- 使用@Computed定义计算属性,自动响应状态变化
- 状态变化时自动触发UI更新,无需手动干预
6. 最佳实践
6.1 组件化开发
// 抽取数据卡片为独立组件
@Component
struct DataCard {@Prop cardData: DashboardCardItembuild() {Column() {Text(this.cardData.title).fontSize(14).fontColor('#666').margin({bottom: 12})Flex({alignItems: ItemAlign.Baseline}) {Text(this.cardData.value).fontSize(28).fontWeight(FontWeight.Bold).fontColor(this.cardData.color)Text(this.cardData.unit).fontSize(14).fontColor(this.cardData.color).margin({left: 4})}.margin({bottom: 8})Text(this.cardData.trend).fontSize(14).fontColor(this.cardData.trend.includes('+') ? '#2A9D8F' : '#E76F51')}.width('100%').padding(16).backgroundColor('#FFFFFF').borderRadius(12)}
}// 在主组件中使用
ForEach(this.dataCards, (card: DashboardCardItem) => {DataCard({ cardData: card })
})
组件化开发的优势:
- 提高代码复用率
- 简化主组件逻辑
- 便于维护和测试
- 支持团队协作开发
6.2 样式与逻辑分离
// 样式常量
const CARD_STYLES = {container: {width: '100%',padding: 16,borderRadius: 12,backgroundColor: '#FFFFFF'},title: {fontSize: 14,fontColor: '#666',marginBottom: 12},// 其他样式...
}// 在组件中使用
@Component
struct StyledCard {@Prop data: CardDatabuild() {Column() {Text(this.data.title).fontSize(CARD_STYLES.title.fontSize).fontColor(CARD_STYLES.title.fontColor).margin({bottom: CARD_STYLES.title.marginBottom})// 其他UI元素...}.width(CARD_STYLES.container.width).padding(CARD_STYLES.container.padding).backgroundColor(CARD_STYLES.container.backgroundColor).borderRadius(CARD_STYLES.container.borderRadius)}
}
样式与逻辑分离的好处:
- 提高代码可读性
- 便于统一管理和修改样式
- 支持主题切换
- 减少重复代码
7. 总结
本文详细介绍了HarmonyOS仪表盘应用的进阶开发技巧,包括:
- 响应式设计:通过屏幕适配和弹性布局实现多设备适配
- 数据展示与交互:实现数据卡片渲染和图表区域的交互功能
- 事件处理机制:通过点击事件和手势交互增强用户体验
- 性能优化技巧:使用懒加载和状态管理优化提高应用性能
- 数据流管理:实现单向数据流和响应式数据绑定
- 最佳实践:采用组件化开发和样式与逻辑分离的开发模式
通过这些技巧,开发者可以构建出高性能、易维护且用户体验良好的HarmonyOS仪表盘应用。
相关文章:

03 HarmonyOS Next仪表盘案例详解(二):进阶篇
温馨提示:本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦! 文章目录 前言1. 响应式设计1.1 屏幕适配1.2 弹性布局 2. 数据展示与交互2.1 数据卡片渲染2.2 图表区域 3. 事件处理机制3.1 点击事件处理3.2 手势…...

mysql进阶(三)
MySQL架构和存储引擎 1. MySQL架构 MySQL8.0服务器是由连接池、服务管理⼯具和公共组件、NoSQL接⼝、SQL接⼝、解析器、优化 器、缓存、存储引擎、⽂件系统组成。MySQL还为各种编程语⾔提供了⼀套⽤于外部程序访问服务器 的连接器。整体架构图如下所⽰: 2. 连接层 …...
MySQL 架构、索引优化、DDL解析、死锁排查
私人博客传送门 MySQL 认识索引 | 魔筝炼药师 MySQL 索引优化 | 魔筝炼药师 OnlineDDL(在 MySQL 5.7 数据库里,InnoDB引擎,执行一条DDL会发生什么事情) | 魔筝炼药师 MySQL 死锁排查 | 魔筝炼药师...
AVM 环视拼接 鱼眼相机
https://zhuanlan.zhihu.com/p/651306620 AVM 环视拼接方法介绍 从内外参推导IPM变换方程及代码实现(生成AVM环视拼接图)_avm拼接-CSDN博客 经典文献阅读之--Extrinsic Self-calibration of the Surround-view System: A Weakly... (环视系统的外参自…...
【Flink银行反欺诈系统设计方案】5.反欺诈系统全生命周期设计
【Flink银行反欺诈系统设计方案】反欺诈系统全生命周期设计 概要:1. 事前反欺诈准备核心模块与架构: 2. 事中反欺诈发现与告警核心模块与架构: 3. 事后反欺诈事件分析核心模块与架构: 4. 反欺诈闭环架构设计整体技术栈:…...

aardio - 虚表 —— 两个虚表之间互相拖动交换数据
插入到虚表末尾的方法: import win.ui; import godking.vlistEx; /*DSG{{*/ mainForm win.form(text"vlistEx - table adapter";right849;bottom578;border"thin") mainForm.add( radiobutton{cls"radiobutton";text"移动&qu…...

VScode 中文符号出现黄色方框的解决方法
VScode 中文符号出现黄色方框的解决方法 我的vscode的python多行注释中会将中文字符用黄色方框框处: 只需要打开设置搜索unicode,然后将这一项的勾选取消掉就可以了: 取消之后的效果如下: 另一种情况:中文显示出现黄色…...

LINUX网络基础 [二] - 网络编程套接字,UDP与TCP
目录 前言 一. 端口号的认识 1.1 端口号的作用 二. 初识TCP协议和UDP协议 2.1 TCP协议 TCP的特点 使用场景 2.2 UDP协议 UDP的特点 使用场景 2.3 TCP与UDP的对比 2.4 思考 2.5 总结 三. 网络字节序 3.1 网络字节序的介绍 3.2 网络字节序思考 四. socket接口 …...

Spring统一格式返回
目录 一:统一结果返回 1:统一结果返回写法 2:String类型报错问题 解决方法 二:统一异常返回 统一异常返回写法 三:总结 同志们,今天咱来讲一讲统一格式返回啊,也是好久没有讲过统一格式返…...
Unity多Pass渲染与GPU Instancing深度优化指南
一、技术背景与挑战 1. 多Pass渲染的定位 多Pass渲染策略通过单个Shader中定义多个渲染阶段(如阴影生成、光照计算、后处理等)实现复杂视觉效果,但传统实现会显著增加DrawCall数量。例如标准渲染管线中,一个物体可能经历Base Pa…...
Redis高频面试题10个
1. Redis 的特点及与 Memcached 的区别 特点: 基于内存的键值数据库,支持持久化(RDB/AOF)。 单线程模型,通过 IO 多路复用实现高并发。 支持多种数据结构:字符串、哈希、列表、集合、有序集合等。 提供…...
【数据库】MySQL常见聚合查询详解
在数据库操作中,聚合查询是非常重要的一部分。通过聚合查询,我们可以对数据进行汇总、统计和分析。MySQL提供了丰富的聚合函数来满足不同的需求。本文将详细介绍MySQL中常见的40个聚合函数及其使用场景,并通过8个的案例展示它们的用法。 一、…...

蓝桥备赛(11)- 数据结构、算法与STL
一、数据结构 1.1 什么是数据结构? 在计算机科学中,数据结构是一种 数据组织、管理和存储的格式。它是相互之间存在一种 或多种特定关系的数据元素的集合。 ---> 通俗点,数据结构就是数据的组织形式 , 研究数据是用什么方…...

Linux的系统ip管理
ip地址 命令:ifconfig 127.0.0.1这个ip地址用于指本机。 0.0.0.0特殊ip地址用于指代本机,可以在端口绑定中用来确定绑定关系,在一些ip地址限制中,表示所有ip的意思。如放行规则设置为0.0.0.0,表示允许任意ip访问。 …...

【决策树】分类属性的选择
文章目录 1.信息增益(ID3)2.信息增益率(C4.5)3.基尼指数(CART)ps.三者对比 实现决策树算法最关键的一点就是如何从所有的特征属性中选择一个最优的属性对样本进行分类,这种最优可以理解为希望划…...

uniapp vue3 微信小程序 uni.chooseLocation使用
申请 先要去微信公众平台申请使用接口 开通成功之后就可以在项目中配置使用了 配置 配置manifest.json "mp-weixin": {/* 小程序特有相关 */"requiredPrivateInfos": ["chooseLocation"],"permission": {"scope.userLocati…...

9. Flink的性能优化
1. Flink的资源和代码优化 1.1 slot资源配置 Flink中具体跑任务的进程叫TaskManager,TM进程又会根据配置划分出诺干个TaskSlot,它是具体运行SubTask的地方。slot是Flink用来隔离各个subtask的资源集合,这里的资源一把指内存,TCP…...

十二、OSG学习笔记-Control
上一章节: 十一、OSG学习笔记-操作系统接口-CSDN博客https://blog.csdn.net/weixin_36323170/article/details/145891502 本章节代码: OsgStudy/Controls CuiQingCheng/OsgStudy - 码云 - 开源中国https://gitee.com/cuiqingcheng/osg-study/tree/ma…...
集群、分布式与微服务架构 区别
集群、分布式与微服务架构:概念解析与核心差异 在构建现代软件系统时,集群架构、分布式系统和微服务架构是三种常见的技术方案。它们常被混淆,但各自解决的问题、设计理念和应用场景截然不同。本文将从基础概念出发,深入分析三者…...
如何使用SSH命令安全连接并转发端口到远程服务器
ssh -p 22546 rootconnect.westc.gpuhub.com d6IS/mQKq/iG ssh -CNgv -L 6006:127.0.0.1:6006 rootconnect.westc.gpuhub.com -p 22546 第一条命令:用于登录远程服务器,进行交互式操作。第二条命令:用于建立 SSH 隧道,进行端口转…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...
逻辑回归:给不确定性划界的分类大师
想象你是一名医生。面对患者的检查报告(肿瘤大小、血液指标),你需要做出一个**决定性判断**:恶性还是良性?这种“非黑即白”的抉择,正是**逻辑回归(Logistic Regression)** 的战场&a…...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...

2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...

srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...