目录:
- 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();
@Builder
tabBarBuilder(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();
@Builder
quickStartRouter(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 = id
this.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)
}
}
}