目录:
- 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)}}
}