HarmonyOS三层架构实战
目录:
- 1、三层架构项目结构
- 1.0、三层架构简介
- 1.1、 common层(主要放一些公共的资源等)
- 1.2、 features层(主要模块定义的组件以及图片等静态资源)
- 1.3、 products层(主要放主页面层和一些主要的资源,内部快速入门,课程学习,知识地图等都是模块放在features层)
- 1.4、MVVM模式
- 2、products主页面
- 3、快速入门模块
- QuickStartPage.ets
- Banner.ets
- bufferToString.ets
- BannerClass.ets
- EnablementView.ets
- TutorialView.ets
- ArticleClass.ets
- 4、课程学习模块
- CourseLearning.ets
- 5、知识地图模块
1、三层架构项目结构

这里新建三个文件夹不是模块,来构建鸿蒙项目的三层架构。
1.0、三层架构简介

1.1、 common层(主要放一些公共的资源等)

1.2、 features层(主要模块定义的组件以及图片等静态资源)

1.3、 products层(主要放主页面层和一些主要的资源,内部快速入门,课程学习,知识地图等都是模块放在features层)

1.4、MVVM模式


2、products主页面
这里放置的都是一些跟主页面相关的以及入口文件等。

import { CourseLearning } from '@ohos/learning';
import { KnowledgeMap } from '@ohos/map';
import { QuickStartPage } from '@ohos/quickstart';@Entry
@Component
struct Index {@State currentIndex: number = 0;private tabsController: TabsController = new TabsController();@BuildertabBarBuilder(title: string, targetIndex: number, selectedIcon: Resource, unselectIcon: Resource) {Column() {Image(this.currentIndex === targetIndex ? selectedIcon : unselectIcon).width(24).height(24)Text(title).fontFamily('HarmonyHeiTi-Medium').fontSize(10).fontColor(this.currentIndex === targetIndex ? '#0A59F7' : 'rgba(0,0,0,0.60)').textAlign(TextAlign.Center).lineHeight(14).fontWeight(500)}.width('100%').height('100%').justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Center).onClick(() => {this.currentIndex = targetIndex;this.tabsController.changeIndex(targetIndex);})}build() {Tabs({ barPosition: BarPosition.End, controller: this.tabsController }) {TabContent() {QuickStartPage()}.tabBar(this.tabBarBuilder('快速入门', 0, $r('app.media.ic_01_on'), $r('app.media.ic_01_off')))TabContent() {CourseLearning()}.tabBar(this.tabBarBuilder('课程学习', 1, $r('app.media.ic_02_on'), $r('app.media.ic_02_off')))TabContent() {KnowledgeMap()}.tabBar(this.tabBarBuilder('知识地图', 2, $r('app.media.ic_03_on'), $r('app.media.ic_03_off')))}.vertical(false).divider({strokeWidth: 0.5,color: '#0D182431'}).scrollable(false).backgroundColor('#F1F3F5').padding({ top: 36, bottom: 28 })}
}
以前导出模块都是在各模块index.ets文件下导出,现在是products依赖feature模块,在oh-package.json5中如下配置即可引入相关依赖。

在module.json5中进行权限配置(这里其他模块需要的权限都在products中的这个配置文件中配置即可)。

3、快速入门模块

QuickStartPage.ets
import { TutorialView } from '../view/TutorialView';
import { ArticleClass } from '../model/ArticleClass'
import { ArticleDetailPage } from './ArticleDetailPage';
import { Banner } from '../view/Banner';
import { EnablementView } from '../view/EnablementView';
import { BannerDetailPage } from './BannerDetailPage';
import { BannerClass } from '../model/BannerClass';@Component
export struct QuickStartPage {@State message: string = '快速入门';@Provide('articlePathStack') articlePathStack: NavPathStack = new NavPathStack();@BuilderquickStartRouter(name: string, param?: ArticleClass | BannerClass) {if (name === 'articleDetail') {ArticleDetailPage()} else if (name === 'bannerDetailPage') {BannerDetailPage()}}build() {Navigation(this.articlePathStack) {Column() {Text(this.message).fontSize(24).fontWeight(700).width('100%').textAlign(TextAlign.Start).padding({ left: 16 }).fontFamily('HarmonyHeiTi-Bold').lineHeight(33)//此处采用Scroll作为外层容器,是由于其内部内容很有可能会超过屏幕高度,为保证内容显示,可以采用Scroll组件来进行滚动显示。scrollBar设置为BarState.Off,表示关闭滚动时的滚动条显示Scroll() {Column() {//轮播图广告组件Banner()//赋能组件EnablementView()//入门教程TutorialView()}}.layoutWeight(1).scrollBar(BarState.Off).align(Alignment.TopStart)}.width('100%').height('100%').backgroundColor('#F1F3F5')}.navDestination(this.quickStartRouter).hideTitleBar(true).mode(NavigationMode.Stack)}
}
Banner.ets
import { BannerClass } from '../model/BannerClass';
import { bufferToString } from '../util/BufferUtil';@Component
export struct Banner {@Consume('articlePathStack') articlePathStack: NavPathStack;@State bannerList: BannerClass[] = [];aboutToAppear(): void {//在组件初始化时就加载数据this.getBannerDataFromJSON()}//在Banner中,定义一个方法getBannerDataFromJson,并通过ResourceManager获取当前工程目录下rawfile中的json文件内容。//转换内容需要两个步骤://1、将获取的buffer内容转换为字符串//2、将字符串转换为页面数据结构//因为预览器并不支持获取rawfile目录下的文件,所以无法成功获取到保存在rawfile目录下的json文件里的内容。请用真机/模拟器测试,预览器仅支持简单页面的预览getBannerDataFromJSON() {getContext(this).resourceManager.getRawFileContent('BannerData.json').then(value => {this.bannerList = JSON.parse(bufferToString(value)) as BannerClass[];})}clickToDetailPage(item: BannerClass) {this.articlePathStack.pushPathByName('bannerDetailPage', item);}build() {//Swiper组件作为容器可以使轮播图具有轮播的效果Swiper() {ForEach(this.bannerList, (item: BannerClass) => {//$r("字符串类型的")Image($r(item.imageSrc)).objectFit(ImageFit.Contain) //保持宽高比进行缩小或者放大.width('100%').borderRadius(16).padding({ top: 11, left: 16, right: 16 }).onClick(() => {this.clickToDetailPage(item)})}, (item: BannerClass) => item.id)}//autoPlay控制是否自动轮播子组件,loop属性控制是否循环播放,indicator属性自定义导航点的位置和样式.autoPlay(true).loop(true).indicator(new DotIndicator().color('#1a000000').selectedColor('#0A59F7'))}
}
bufferToString.ets
import { util } from '@kit.ArkTS';
//由于ResourceManager获取到的是Uint8Array类型的内容,所以需要将对应的内容转换为字符串,并将字符串解析为对应的数据结构。考虑到其他的文件也会使用这个公共方法,可以新建一个util文件夹,并创建一个BufferUtil文件,实现这个字符串转换方法
export function bufferToString(buffer: Uint8Array): string {let textDecoder = util.TextDecoder.create('utf-8', {ignoreBOM: true});let resultPut = textDecoder.decodeToString(buffer);return resultPut;
}
BannerClass.ets
export class BannerClass {id: string = '';imageSrc: string = '';url: string = ''constructor(id: string, imageSrc: string, url: string) {this.id = idthis.imageSrc = imageSrc;this.url = url;}
}
EnablementView.ets
import { ArticleClass } from '../model/ArticleClass';
import { bufferToString } from '../util/BufferUtil';@Component
export struct EnablementView {@State enablementList: ArticleClass[] = [];@Consume('articlePathStack') articlePathStack: NavPathStack;aboutToAppear(): void {----------this.getEnablementDataFromJSON()}getEnablementDataFromJSON() {getContext(this).resourceManager.getRawFileContent('EnablementData.json').then(value => {this.enablementList = JSON.parse(bufferToString(value)) as ArticleClass[];})}build() {Column() {Text('赋能套件').fontColor('#182431').fontSize(16).fontWeight(500).fontFamily('HarmonyHeiTi-medium').textAlign(TextAlign.Start).padding({ left: 16, right: 16 }).width('100%')Grid() {ForEach(this.enablementList, (item: ArticleClass) => {GridItem() {EnablementItem({ enablementItem: item }).onClick(() => {this.articlePathStack.pushPathByName('articleDetail', item)})}}, (item: ArticleClass) => item.id)}.rowsTemplate('1fr').columnsGap(8).scrollBar(BarState.Off).height(169).padding({ top: 2, left: 16, right: 16 })}.margin({ top: 18 })}
}@Component
export struct EnablementItem {@Prop enablementItem: ArticleClass;build() {Column() {Image($r(this.enablementItem.imageSrc)).width('100%')//设置填充效果为cover模式,即保持宽高比进行缩小或者放大,使得图片两边都大于或等于显示边界.objectFit(ImageFit.Cover).height(96).borderRadius({topLeft: 16,topRight: 16})Text(this.enablementItem.title).height(19).width('100%').fontSize(14).textAlign(TextAlign.Start)//textOverFlow属性设置文本超长时的显示方式,在这里我们设置它的值为Ellipsis,表示超长时使用省略号替代.textOverflow({ overflow: TextOverflow.Ellipsis }).maxLines(1).fontWeight(400).padding({ left: 12, right: 12 }).margin({ top: 8 })Text(this.enablementItem.brief).height(32).width('100%').fontSize(12).textAlign(TextAlign.Start).textOverflow({ overflow: TextOverflow.Ellipsis }).maxLines(2).fontWeight(400).fontColor('rgba(0, 0, 0, 0.6)').padding({ left: 12, right: 12 }).margin({ top: 2 })}.width(160).height(169).borderRadius(16).backgroundColor(Color.White)}
}
TutorialView.ets
import { bufferToString } from '../util/BufferUtil';
import { ArticleClass } from '../model/ArticleClass';@Component
export struct TutorialView {@State tutorialList: ArticleClass[] = [];@Consume('articlePathStack') articlePathStack: NavPathStack;aboutToAppear(): void {this.getTutorialDataFromJSON()}getTutorialDataFromJSON() {getContext(this).resourceManager.getRawFileContent('TutorialData.json').then(value => {this.tutorialList = JSON.parse(bufferToString(value)) as ArticleClass[];})}build() {Column() {Text('入门教程').fontColor('#182431').fontSize(16).fontWeight(500).fontFamily('HarmonyHeiTi-medium').textAlign(TextAlign.Start).padding({ left: 16, right: 16 }).width('100%')List({ space: 12 }) {ForEach(this.tutorialList, (item: ArticleClass) => {ListItem() {TutorialItem({ tutorialItem: item }).onClick(() => {this.articlePathStack.pushPathByName('articleDetail', item)})}}, (item: ArticleClass) => item.id)}.scrollBar(BarState.Off).padding({ left: 16, right: 16 })}.margin({ top: 18 }).alignItems(HorizontalAlign.Start)}
}@Component
export struct TutorialItem {@Prop tutorialItem: ArticleClass;build() {Row() {Column() {Text(this.tutorialItem.title).height(19).width('100%').fontSize(14).textAlign(TextAlign.Start).textOverflow({ overflow: TextOverflow.Ellipsis }).maxLines(1).fontWeight(400).margin({ top: 4 })Text(this.tutorialItem.brief).height(32).width('100%').fontSize(12).textAlign(TextAlign.Start).textOverflow({ overflow: TextOverflow.Ellipsis }).maxLines(2).fontWeight(400).fontColor('rgba(0, 0, 0, 0.6)').margin({ top: 5 })}.height('100%')//设置layoutWeight属性,取值为1,表示它们在任意尺寸的设备下自适应占满剩余空间.layoutWeight(1).alignItems(HorizontalAlign.Start).margin({ right: 12 })Image($r(this.tutorialItem.imageSrc)).objectFit(ImageFit.Cover).height(64).width(108).borderRadius(16)}.width('100%').height(88).borderRadius(16).backgroundColor(Color.White).padding(12).alignItems(VerticalAlign.Top)}
}
ArticleClass.ets
export class ArticleClass {id: string = '';imageSrc: string = '';title: string = '';brief: string = '';webUrl: string = '';constructor(id: string, imageSrc: string, title: string, brief: string, webUrl: string) {this.id = id;this.imageSrc = imageSrc;this.title = title;this.brief = brief;this.webUrl = webUrl;}
}
4、课程学习模块
CourseLearning.ets
import { webview } from '@kit.ArkWeb';@Component
export struct CourseLearning {//创建webviewController,开发者后续可以通过该Controller控制Web组件加载的界面private webviewController: webview.WebviewController = new webview.WebviewController();build() {Column() {Web({ src: $rawfile('course_learning/index.html'), controller: this.webviewController }).domStorageAccess(true)}}
}
5、知识地图模块
相关文章:
HarmonyOS三层架构实战
目录: 1、三层架构项目结构1.0、三层架构简介1.1、 common层(主要放一些公共的资源等)1.2、 features层(主要模块定义的组件以及图片等静态资源)1.3、 products层(主要放主页面层和一些主要的资源ÿ…...
计算机四级 - 数据库原理 - 第4章 「关系数据库标准语言SQL」
4.1 SQL概述 4.1.1 结构化查询语言SQL SQL(Structured Query Language)称为结构化查询语言,它是由1974年由Boyce和Chamberi提出的,1975年至1979年IBM公司的San Jose Research Laboratory研制了关系数据库管理系统的原型系统System R,并实现了这种语198…...
基于PMU的14节点、30节点电力系统状态估计MATLAB程序
“电气仔推送”获得资料(专享优惠) 程序简介: 程序采用三种方法对14节点和30节点电力系统状态进行评估: ①PMU同步向量测量单元结合加权最小二乘法(WLS)分析电力系统的电压幅值和相角状态; …...
JS超过Number的最大值
场景:用户输入(这个可以通过前端限制输入长度控制)或正规场景,大数据量展示 Number类型的最大值是2^53 - 1 解决方案一:BigInt BigInt 是 JavaScript 中专门用来表示任意精度整数的类型。它允许你处理超出 Number 范围的整数。 const bigNu…...
Deepseek API+Python测试用例一键生成与导出-V1.0.2【实现需求文档图片识别与用例生成自动化】
在测试工作中,需求文档中的图片(如界面设计图、流程图)往往是测试用例生成的重要参考。然而,手动提取图片并识别内容不仅耗时,还容易出错。本文将通过一个自研小工具,结合 PaddleOCR 和大模型,自…...
整形在内存中的存储(例题逐个解析)
目录 一.相关知识点 1.截断: 2.整形提升: 3.如何 截断,整型提升? (1)负数 (2)正数 (3)无符号整型,高位补0 注意:提升后得到的…...
基于变分推理与 Best‑of‑N 策略的元 Prompt 自动生成与优化框架
摘要 本文提出了一种融合变分推理与 Best‑of‑N 策略的元 Prompt 自动生成与优化框架,通过高度参数化的模板、随机扰动采样及多指标评分机制,实现从初始提示生成到最终输出的动态优化。同时,针对实际应用中对自适应参数调整、深层语义理解、…...
AI 技术在智慧农业中的应用实践
智慧农业是通过现代信息技术(如物联网、大数据、人工智能等)提升农业生产效率、降低资源消耗、改善农产品质量的现代农业模式。AI 技术在智慧农业中的应用实践涵盖了从种植到收获的全流程,以下是具体的方案和应用场景: 1. AI 在智慧农业中的应用场景 1.1 精准种植 应用场景…...
蓝牙系统的核心组成解析
一、硬件层:看得见的物理载体 1. 射频模块(Radio Frequency Module) 专业描述:工作在2.4GHz ISM频段,支持GFSK/π/4 DQPSK/8DPSK调制方式 功能类比:相当于人的"嘴巴"和"耳朵" 发射端…...
centos 7误删/bash 拯救方法
进入救援模式 1. 插入CentOS 7安装光盘,重启系统。在开机时按BIOS设置对应的按键(通常是F2等),将启动顺序调整为CD - ROM优先。 2. 系统从光盘启动后,选择“Troubleshooting”,然后选择“Rescue a Cent…...
uniapp笔记-底部和首部标签页菜单生成
逻辑 这些都是需要配置pages.json文件。 其中底部需要手动配置tarBar,如: "tabBar": {"list":[{"pagePath": "pages/index/index","text": "首页"},{"pagePath": "pages/…...
基于Gemini 生成 Gemini Embedding
在本报告中,我们介绍了Gemini Embedding,这是一款基于谷歌功能最强大的大型语言模型Gemini的先进嵌入模型。借助Gemini的多语言和代码理解能力,Gemini Embedding能够为多种语言和文本模态的文本生成高度通用的嵌入表示。Gemini Embedding生成的表示可以预先计算并应用于多种…...
SpringBoot 和vue前后端配合开发网页拼图10关游戏源码技术分享
今天分享一个 前后端结合 的网页游戏 开发项目源码技术。 这也是我第一次写游戏类的程序,虽然不是特别复杂的游戏,但是是第一次写,肯定要记录一下了,哈哈。 游戏的内容 就是 我们显示中玩的那个 拼图碎片的 游戏,类似下…...
OpenCV计算摄影学(21)非真实感渲染之边缘保留滤波器edgePreservingFilter()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 滤波是图像和视频处理中的基础操作。边缘保留平滑滤波器被广泛应用于多种不同场景[98]。 cv::edgePreservingFilter 是一种边缘保留滤波器&#…...
Qemu 详解与 ARM 虚拟机搭建指南
1. Qemu 是什么? Qemu(Quick Emulator)是一款开源的机器模拟器和虚拟化工具,支持多种硬件架构(如 x86、ARM、PowerPC 等)。它的核心功能包括: 动态指令翻译:将不同架构的指令实时翻…...
JVM并发编程AQSsync锁ReentrantLock线程池ThreadLocal
并发编程2 synchronized锁实现**AQS****ReentrantLock实现****JUC 常用类**池的概念 ThreadLocalThreadLocal原理内存泄露强引用:软引用弱引用虚引用ThreadLocal内存泄露 synchronized锁实现 synchronized是一个关键字,实现同步,还需要我们提供一个同步锁对象,记录锁状态,记录…...
CMake学习笔记(三):静态库,动态库的生成和使用
一:动态库 接下来我们简单的讲解下动态库的建立和使用:在后面的项目的开发过程中,我们使用第三方库或者我们跑这个项目的时候我们总会看到一些.so的文件,这些就是所谓的动态库,里面的内容就是编译后的源文件,是程序运行时被加载和…...
《Classifier-Free Diffusion Guidance》的核心观点与方法
介绍《Classifier-Free Diffusion Guidance》的核心观点与方法 在扩散模型(Diffusion Models)的研究中,如何在生成样本的质量与多样性之间找到平衡一直是核心挑战之一。传统的生成模型(如GANs或Glow)通过截断…...
什么是数学建模?数学建模是将实际问题转化为数学问题
数学建模是将实际问题转化为数学问题,并通过数学工具进行分析、求解和验证的过程。 一、数学建模的基本流程 问题分析 • 明确目标:确定需要解决的核心问题。 • 简化现实:识别关键变量、忽略次要因素。 • 定义输入和输出:明确模…...
唤起“队列”的回忆
又来博客记录自己的学习心得了,嘿嘿嘿(^~^) 目录 队列的概念和结构: 队列的创建和初始化: 队列入栈: 队列出栈: 队列的销毁: 取队头和队尾数据: 结语: 队列的概念…...
Linux(8.4)NFS
文章目录 一、概念二、详解NFS1)软件名2)服务名3)配置文件4)端口号5)相关命令 三、部署NFS一、NFS服务端1)**配置源(本地或者网络源)**2)2、安装NFS**3)启动服…...
【位运算】速算密钥:位运算探秘
文章目录 前言例题一、判定字符是否唯一二、丢失的数字三、两整数之和四、只出现⼀次的数字 II五、消失的两个数字 结语 前言 什么是位运算算法呢? 位运算算法是以位运算为核心操作,设计用来高效解决特定问题的一系列计算步骤集合。它巧妙利用位运算直接…...
STM32G070CBT6读写FLASH中的数据
向FLASH中写入数据函数 /*函数说明:向FLASH中写数据形参:addr-要写入数据的起始地址 data-准备写入数据 len-数据大小返回值:1-成功,0-失败 */ uint8_t FlashWriteData(uint64_t addr,uint8_t data[],size_t len) {uint32_t Fir…...
算法刷题记录——LeetCode篇(4) [第301~400题](持续更新)
(优先整理热门100及面试150,不定期持续更新,欢迎关注) 322. 零钱兑换 给你一个整数数组 coins ,表示不同面额的硬币;以及一个整数 amount ,表示总金额。 计算并返回可以凑成总金额所需的最少的硬币个数。如果没有任何…...
目标检测任务,如何区分两个相近似的目标
首先,要了解清楚检测的场景下,肉眼能否区分出目标的差异性。 如果可以区分,那观察数据周围背景的差异是否较大,可以先通过添加样本来提升模型的检测精度。添加样本时一定要注意,样本标注的准确性,样本的丰…...
中国在 AI 上超越美国,需要另辟蹊径
在过去的几年里,以大型语言模型(LLM)为核心的人工智能浪潮席卷全球。美国凭借其雄厚的科研基础、顶尖的技术公司以及掌握着关键硬件资源,牢牢占据了这一领域的领先地位。与此同时,中国在AI领域的进步虽然迅速ÿ…...
【实习经历Two:参与开源项目,学习并应用Git】
前端参与开源项目中使用过的git 1.参与开源项目(必备技能——git) 参与开源项目首先需要进入自己想参加的项目页面 点击右边的Fork即可复制到自己的仓库 像个人开发时常用的add、commit和push等命令就不过多介绍了,在这里主要是想记录一下自己作为从未…...
AD绘图基本操作
一、基本操作 注意:快捷键都要在英文模式下才能生效 1、移动 按住鼠标右键移动 2、切换桌面栅格距离 G 3、英寸和毫米 尺寸切换 Q 4、元件在3D模式下的移动 3D视角鼠标左键只起到选择元器件并移动之的功能, 单纯鼠标右键只能平移桌面 shift鼠…...
6k ± 1 规则
6k 1 规则 是基于对质数分布规律的观察和数学证明得出的。它指出,除了 2 和 3 之外,所有质数都可以表示为 6k 1 的形式,其中 k 是正整数。以下是详细的证明过程: 1. 质数的基本性质 质数是指大于 1 的自然数,且只能…...
AcWing 5960:输出前k大的数 ← 小根堆
【题目来源】 https://www.acwing.com/problem/content/5963/ 【题目描述】 给定一个长度为 n 的数组 a1,a2,…,an,统计前 k 大的数并且把这 k 个数从大到小输出。 【输入格式】 第一行包含整数 n。 第二行包含 n 个整数 a1,a2,…,an。 第三行包含整数 k。…...
