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

上一篇:

重生之我在大学自学鸿蒙开发第一天-《基础篇》-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

Banner

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)
  }
}
相关推荐
你真的可爱呀4 小时前
uniapp学习【vue3在uniapp中语法,使用element,使用uView UI】
学习·uni-app
安卓开发者4 小时前
鸿蒙NEXT USB Host模式开发完全指南
华为·harmonyos
2501_916766544 小时前
【Git学习】初识git:简单介绍及安装流程
git·学习
哈基鑫4 小时前
手写数字识别学习笔记
笔记·学习
im_AMBER4 小时前
Web 开发 29
前端·学习·web
缘友一世4 小时前
活动目录的枚举学习
学习·网络安全·网路攻击
Da Da 泓4 小时前
shellSort
java·数据结构·学习·算法·排序算法
润 下5 小时前
C语言——深入解析C语言指针:从基础到实践从入门到精通(三)
c语言·开发语言·经验分享·笔记·学习·程序人生·其他
焚 城5 小时前
UniApp中Flex布局学习
学习·uni-app