当前位置: 首页 > news >正文

重生之我在大学自学鸿蒙开发第二天-《MVVM模式》

  • 个人主页:VON
  • 文章所属专栏:从0开始的开源鸿蒙6.0.0
  • 个人抖音:清洒

上一篇:

重生之我在大学自学鸿蒙开发第一天-《基础篇》-CSDN博客

目录

一、前言

二、实践

2.1、简述MVVM

2.2、改造model文件

2.3、改造view文件

2.4、改造rawfile文件夹

1、将获取的buffer内容转换为字符串

2、将字符串转换为页面数据结构

3、整体逻辑如下

4、页面的生命周期执行流程

2.5、改造Banner

数据获取

2.6、改造EnablementView和TutorialView

三、测试

四、源码展示

ArticleClass

BannerClass

Index

BufferUtil

EnablementView

TutorialView


一、前言

在上一篇文章中完成了单独页面的创建,并没有进行分层,导致代码十分冗余,如果想要开发更复杂的APP肯定不能这样写,开发过java的都知道分为三层架构,鸿蒙也是这样也是三层架构的模式,本篇文章主要讲解应用架构设计基础——MVVM模式。废话不多说直接开肝!

官方文档:应用架构设计基础——MVVM模式-HarmonyOS应用开发快速入门-Codelabs-华为开发者联盟

二、实践

本章内容并不复杂,主要三层架构模式见下一章

2.1、简述MVVM

MVVM = Model + View + ViewModel模式,其中状态管理模块起到的就是ViewModel的作用,将数据与视图绑定在一起,更新数据的时候直接更新视图。

2.2、改造model文件

model文件夹用于存储数据模型。它表示组件或其他相关业务逻辑之间传输的数据,是对原始数据的进一步处理。

创建文件的时候看清楚,我刚开始就没看清点击的上面那个导致没有创建成功,这里大家注意下。

这里将Class给提取出来放到model文件中。

导出的时候别忘了使用export进行导出然后再直接import导入即可

2.3、改造view文件

view文件夹主要用于存储UI组件,也就是昨天所写的EnablementView.ets和TutorialView.ets以及Banner.ets组件。

直接将index中的代码拿过来即可,这里由于代码量太多了就将代码折叠起来了。

2.4、改造rawfile文件夹

官方说明:rawfile目录中的资源文件会被直接打包进应用,不经过编译,也不会被赋予资源文件ID。通过指定文件路径和文件名引用。

第一次听说这个文件,好像是用于存储json数据的文件夹。

可以看到这是原本的数据,我们是用数组进行存储的,现在转为json格式存放再rawfile文件夹里面即可。

json格式的数据想必大家也并不陌生。

接下来引用json数据先定义一个方法getBannerDataFromJson(),并通过ResourceManager获取当前工程目录下rawfile中的json文件内容。

转换内容需要两个步骤:

1、将获取的buffer内容转换为字符串

由于ResourceManager获取到的是Uint8Array类型的内容,所以需要将对应的内容转换为字符串,并将字符串解析为对应的数据结构。考虑到其他的文件也会使用这个公共方法,可以新建一个util文件夹,并创建一个BufferUtil文件,实现这个字符串转换方法。

果然这里需要进行转换

2、将字符串转换为页面数据结构

3、整体逻辑如下

这里的函数不用刻意去记,可以当成一个模板来进行套用,其他两个组件也可以使用此方法来进行转换,只要知道思路即可。

4、页面的生命周期执行流程

2.5、改造Banner

通过上面的生命周期不难发现,aboutToAppear要先于build,做过vue项目的同学应该都清楚,加载页面之前要先获取数据,就像vue中的onMountd(),所以我们这里也要先获取数据

数据获取

官方解释:json中数据由于无法使用$r()进行资源访问,所以使用的是字符串"app.media.banner_pic0",而在页面中直接声明时,使用的是$r('app.media.banner_pic0'),而Image组件是无法直接读取字符串"app.media.banner_pic0"的,所以这里需要进行内容调整。

这里要将imageSrc数据类型修改为string(注意下这里的s是小写)

别忘了ArticleClass类中也要进行修改

这里的图片引用的方式也需要改变下

2.6、改造EnablementView和TutorialView

这两个文件的引用一样,只需要改下名字即可。

三、测试

接下来开始进行真机测试,我这里使用模拟机来进行测试

我这里启动虚拟机的时候出了点问题,因为我的电脑没有开启虚拟化,大家可以参考下面文章来进行查看

关于win11如何打开Hyper-V详解_win11开启hyper-v-CSDN博客

我这里好像无法使用命令行下载,还是直接去官网下载吧

官网下载的是真的慢,因为这是国外的软件

还是用命令行吧,如果上面文章中的命令无法使用的剋试一下这个指令

  • 使用 PowerShell 下载打开 PowerShell(管理员模式),执行以下命令下载最新版本的 Hyper 安装包:

    # 下载 Hyper 安装文件到当前目录
    Invoke-WebRequest -Uri "https://releases.hyper.is/download/win" -OutFile "hyper-setup.exe"
    
  • 命令行安装下载完成后,继续在 PowerShell 中执行安装命令:

    # 运行安装程序(会自动执行安装流程)
    .\hyper-setup.exe
    
  • 静默安装(可选)如果需要无界面静默安装,可以添加参数:

    .\hyper-setup.exe /S

调试了一下午也是终于调试成功,我这里直接将Hyper上传到网盘了,有需要的朋友可以自行提取。

通过网盘分享的文件:Hyper-Setup-3.4.1.exe
链接: https://pan.baidu.com/s/1OM67IrDC3-_Uffew5nXyIg 提取码: 9f9s

整体效果如下

这里出了点问题

注意:这里千万不能马虎,所有用到图片的地方都要这样引用!!!

四、源码展示

整体结构如下👇:

ArticleClass

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;}
}

BannerClass

export class BannerClass{id : string='';imageSrc : string='';url : string = 'https://blog.csdn.net/2302_80329073?type=blog';constructor(id : string,imageSrc : string,url : string) {this.id = id;this.imageSrc = imageSrc;this.url = url;}
}

Index

import { TutorialView } from '../view/TutorialView';
import { Banner } from '../view/Banner';
import { EnablementView } from '../view/EnablementView';
@Entry
@Component
struct Index {@State message: string = 'VON';build() {Column(){Text(this.message).fontSize(24).fontWeight(700).width('100%').padding({left:16}).lineHeight(33).textAlign(TextAlign.Start)Scroll(){Column(){Banner()EnablementView()TutorialView()}}.layoutWeight(1).scrollBar(BarState.Off).align(Alignment.TopStart)}.height('100%').width('100%').backgroundColor('#f1f1f1').padding({top:11,left:16,right:16});}
}

BufferUtil

import { util } from '@kit.ArkTS';//将Uint8Array类型的内容转换为字符串
export function bufferToString(buffer: Uint8Array): string {let textDecoder = util.TextDecoder.create('utf-8', {ignoreBOM: true});let resultPut = textDecoder.decodeToString(buffer);return resultPut;
}
import { BannerClass } from '../model/BannerClass'
import { bufferToString } from '../util/BufferUtil';// Banner组件
@Component
export struct Banner{@State bannerList:Array<BannerClass> = [];aboutToAppear(): void {this.getBannerDataFromJSON();}// 获取json数据并转换为对应类型getBannerDataFromJSON() {this.getUIContext().getHostContext()?.resourceManager.getRawFileContent('BannerData.json').then(value => {this.bannerList = JSON.parse(bufferToString(value)) as BannerClass[];});}build() {Swiper(){ForEach(this.bannerList,(item:BannerClass,index:number)=>{Image($r(item.imageSrc)).objectFit(ImageFit.Contain).width('100%').height(260).borderRadius(16)},(item:BannerClass,index:number)=>item.id)}.autoPlay(true).loop(true).indicator(new DotIndicator().color('#f1f1f1').selectedColor('red'))}
}

EnablementView

import { ArticleClass } from '../model/ArticleClass';
import { bufferToString } from '../util/BufferUtil';@Component
struct EnablementItem{@Prop enablementItem:ArticleClass;build() {Column(){Image($r(this.enablementItem.imageSrc)).width('100%').objectFit(ImageFit.Cover).height(96).borderRadius({topLeft:16,topRight:16})Text(this.enablementItem.title).height(19).width('100%').fontSize(14).textAlign(TextAlign.Start).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(169).height(169).borderRadius(16).backgroundColor(Color.White)}
}@Component
export struct EnablementView {@State enablementList: Array<ArticleClass> = [];aboutToAppear(): void {this.getEnablementDataFromJSON();}// 获取json数据并转换为对应类型getEnablementDataFromJSON() {this.getUIContext().getHostContext()?.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 }).margin({ bottom: 8.5 })Grid() {ForEach(this.enablementList, (item: ArticleClass) => {GridItem() {EnablementItem({ enablementItem: item })}}, (item: ArticleClass) => item.id)}.rowsTemplate('1fr').columnsGap(8).scrollBar(BarState.Off).height(169).padding({ top: 2, left: 16, right: 16 })}.margin({top:18}).alignItems(HorizontalAlign.Start).width('100%')}
}

TutorialView

import { ArticleClass } from '../model/ArticleClass';
import { bufferToString } from '../util/BufferUtil';@Component
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).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).margin({top: 20})}
}@Component
export struct TutorialView {@State tutorialList: Array<ArticleClass> = [];aboutToAppear(): void {this.getTutorialDataFromJSON();}// 获取json数据并转换为对应类型getTutorialDataFromJSON() {this.getUIContext().getHostContext()?.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 }).margin({ bottom: 8.5 })List({ space: 12 }) {ForEach(this.tutorialList, (item: ArticleClass) => {ListItem() {TutorialItem({ tutorialItem: item })}}, (item: ArticleClass) => item.id)}.scrollBar(BarState.Off).padding({ left: 16, right: 16 })}.margin({ top: 18 }).alignItems(HorizontalAlign.Start)}
}

http://www.dtcms.com/a/478344.html

相关文章:

  • Sequence Encoder-based Spatio temporal Knowledge Graph Completion
  • 学习笔记:Vue Router 中的链接匹配机制与样式控制
  • 做彩票网站电话多少钱网站在线建设
  • 网站建设入什么费用站规划在网站建设中的作用
  • c语言-流程控制语句
  • for和while循环,continue和break的用法
  • Redis-持久化之RDB
  • 网站宣传海报科技狂人
  • 哪个网站可以查到个人名下公司wordpress文章为啥数据库中找不到
  • 踏上编程征程,与 Python 共舞
  • 工业相机传感器CCD的原理及基础知识
  • 【电脑操作】如何快速去掉win11操作系统下默认的鼠标右键菜单的显示更多选项
  • 漏洞问题解决—SSL/TLS Not Implemented (verified)(中危)
  • 公司怎么建立自己网站WordPress云虚拟空间
  • C++速通Lambda表达式
  • 微企点做的网站怎么去底下的wordpress首页
  • 高防服务器分为哪几种?香港高防服务器有什么特点?
  • 用 PyTorch 实现 MNIST 手写数字识别:从入门到实践
  • 设计模式篇之 代理模式 Proxy
  • 智联招聘网站建设情况wordpress 注册 密码
  • Mobius Protocol:在“去中心化”逐渐被遗忘的时代,重建秩序的尝试
  • 网站制作公司费用wordpress 宋体、
  • 长宁怎么做网站优化好住房城乡建设门户网站
  • MySQL InnoDB Cluster 高可用集群部署与应用实践(下)
  • commons-rng(伪随机数生成)
  • qemu 串口模拟输入的整个流程
  • 在git commit时利用AI自动生成并填充commit信息
  • 【完整源码+数据集+部署教程】可回收金属垃圾检测系统源码和数据集:改进yolo11-AggregatedAtt
  • HakcMyVM-Crack
  • emmc extcsd寄存器