【中工开发者】鸿蒙——仿当当网计划

打印 上一主题 下一主题

主题 1857|帖子 1857|积分 5571

1. 先容

本学期学习了鸿蒙开发课程,想通过一个小项目检验一下本身所学,下面把该项目总结一下,希望对学习鸿蒙开发的小伙伴提供一些参考。
本次项目《当当网》是一款基于ohm模型的UIAbility OpenHarmony应用开发的册本商城在线购物应用。界面简单直观,让您可以轻松直观地探求您需要的各类册本进行购物。
2. 环境搭建

起首需要完成HarmonyOS开发环境搭建,可参照如下步调进行。
2.1 软件要求


  • DevEco Studio版本:DevEco Studio 3.1 Release。
  • HarmonyOS SDK版本:API version 9。
2.2 硬件要求


  • 设备类型:华为手机或运行在DevEco Studio上的华为手机设备模拟器。
  • HarmonyOS体系:3.1.0 Developer Release。
2.3 环境搭建


  • 安装DevEco Studio。
  • 设置DevEco Studio开发环境,下载HarmonyOS SDK。

3. 项目布局



4. 项目展示

点击应用图标,进入应用界面。
   
  
  当前处于登录页面,由于还没有账号,无法登录,点击“注册账号”进行账号注册。
   
  
  
  注册成功后,利用刚才注册的账号,点击“登录”,进入应用首页。
   
  
  进入应用后,主页界面可以上下滑动,查看各种册本干系概况。点击底部状态栏“分类”,进入册本分类页面,可以根据个人差别爱好挑选各类册本,例如:计算机、文学、励志和艺术,任意选取一本册本,可进入详情页面,查看商品先容。
   
  
  
  挑选完成感爱好的册本后,可以进入底部状态栏的“购物车”页面,就各个商品进行挑选和结算。
   
  
  
  结算完成后界面如下:
   
  最后,可以点击底部状态栏进入“我的”页面,进行个人信息管理和账号退出。
   
  
  
  至此,《当当网》APP所有功能展示完毕,接下来开始对源代码进行解析。
5. 项目解析

本项目主要布局如下:

5.1 注册登录计划

1. 页面布局与UI组件
在 Index.ets 中,整个登录页面的布局是通过 Column 组件来构建的,利用了一些常见的UI组件,如 Text, TextInput, Button, Image 等,来构造用户输入框、按钮等界面元素。
  1. Column() {
  2.   Image($r('app.media.systemLogo')) // Logo图片
  3.     .width(100) // Logo宽度
  4.     .height(100) // Logo高度
  5.     .borderRadius(10) // 圆角效果
  6.     .margin({ top: '100vp', bottom: '8vp' }) // Logo边距
  7.   Text('当当网') // 登录页面标题
  8.     .margin({ top: 10 })
  9.     .fontSize('44fp') // 标题字体大小
  10.     .fontWeight(FontWeight.Medium) // 标题字体粗细
  11.     .fontColor('#182431') // 标题字体颜色
  12. }
复制代码
2. 账号与暗码输入框
账号和暗码输入框利用了自定义的 TextInput 组件,并通过 .inputStyle() 来应用样式,onChange 变乱用于更新状态变量(account 和 password)。
  1. TextInput({ text: this.account, placeholder: '请输入手机号' })
  2.   .maxLength(11) // 最大长度
  3.   .type(InputType.Number) // 输入类型为数字
  4.   .inputStyle() // 应用自定义样式
  5.   .onChange((value: string) => {
  6.     this.account = value; // 更新账号状态
  7.   })
复制代码


  • TextInput 组件用来接收用户输入,maxLength(11) 限制了账号的最大长度为 11 个字符。
  • 通过 onChange 变乱,每次输入厘革时更新 account 状态。
同理,暗码输入框也利用了类似的处理方式,区别在于暗码框的 InputType.Password 类型,确保暗码以潜伏的情势显示。
3. 登录逻辑
登录操作在 login() 方法中实现,起首验证用户输入的账号和暗码是否为空,假如不为空,则进行账号和暗码的验证。
  1. login(): void {
  2.   if (this.account == '') {
  3.     myTools.alertMsg('账号不能为空!')
  4.     return;
  5.   }
  6.   if (this.password == '') {
  7.     myTools.alertMsg('密码不能为空!')
  8.     return;
  9.   }
  10.   if(!AppStorage.get(this.account)){
  11.     myTools.alertMsg('该账号不存在!')
  12.     return;
  13.   }
  14.   if(AppStorage.get(this.account) != this.password){
  15.     myTools.alertMsg('密码错误!')
  16.     return;
  17.   }
  18.   this.isShowProgress = true
  19.   if (this.timeOutId === -1) {
  20.     this.timeOutId = setTimeout(() => {
  21.       this.isShowProgress = false
  22.       this.timeOutId = -1
  23.       router.replaceUrl({
  24.         url: "pages/Home"
  25.       }, router.RouterMode.Single)
  26.     }, 2000)
  27.   }
  28. }
复制代码
功能解析

  • 起首查抄 account 和 password 是否为空,若为空则弹出提示。
  • 利用 AppStorage.get(this.account) 查抄是否存在该账号并验证暗码是否精确。
  • 登录成功后,显示加载进度指示器,并设置2秒的延时模拟登录过程,登录完成后跳转到首页 (pages/Home)。
4. 跳转与进度指示器
登录成功后,利用 router.replaceUrl() 方法跳转到首页,并显示一个进度指示器(LoadingProgress)来告知用户正在进行登录操作。
  1. if (this.isShowProgress) {
  2.   LoadingProgress() // 加载进度组件
  3.     .color('#182431') // 颜色
  4.     .width('30vp') // 宽度
  5.     .height('30vp') // 高度
  6.     .margin({ top: '20vp' }) // 上方边距
  7.   Text('正在登录中,请稍后...')
  8. }
复制代码
这段代码展示了登录时进度条的实现,并在页面加载中显示文本提示。

5.2 首页代码解析(Home.ets、Page001.ets)

1. Tab栏与页面布局
首页通过 Tabs 组件来实现一个具有选项卡功能的布局。 Tabs 组件中的 TabContent 用来显示差别的页面内容, TabBuilder 用来构建每个选项卡的显示内容。
  1. Tabs({ barPosition: BarPosition.End, controller: this.controller }) {
  2.   TabContent() {
  3.     Page001();
  4.   }.tabBar(this.TabBuilder(0, '主页'))
  5.   TabContent() {
  6.     Page002();
  7.   }.tabBar(this.TabBuilder(1, '分类'))
  8.   TabContent() {
  9.     Page003();
  10.   }.tabBar(this.TabBuilder(2, '购物车'))
  11.   TabContent() {
  12.     Page004();
  13.   }.tabBar(this.TabBuilder(3, '我的'))
  14. }
复制代码
功能解析

  • Tabs 组件创建了四个选项卡:主页、分类、购物车和我的。
  • 每个 TabContent 显示一个页面 (Page001, Page002, Page003, Page004),并通过 tabBar() 方法绑定相应的标签标题。
2. 选项卡切换
onChange 变乱监听选项卡切换时,更新当前选中的索引值 currentIndex,并根据选中的 tab 显示差别的页面内容。
  1. .onChange((index: number) => {
  2.   this.currentIndex = index;
  3. })
复制代码
这段代码确保在用户点击差别选项卡时,选中的 tab 索引值会被更新,从而动态修改选项卡内容的显示。
3. 自定义Tab样式
TabBuilder 函数用来天生每个 tab 的外观,动态更新文字颜色、大小和分割线的显示。
  1. Text(name)
  2.   .fontColor(this.currentIndex === index ? this.selectedFontColor : this.fontColor)
  3.   .fontSize(this.currentIndex === index ? 16 : 15)
  4.   .fontWeight(this.currentIndex === index ? 500 : 400)
  5.   .lineHeight(22)
  6.   .margin({ top: 7, bottom: 9 })
  7. Divider()
  8.   .strokeWidth(2)
  9.   .color('#007DFF')
  10.   .opacity(this.currentIndex === index ? 1 : 0)
复制代码


  • 当选中该 tab 时,文字颜色变为 selectedFontColor,字体加粗,并显示分割线;否则规复为默认样式。
4.热门推荐部分
接下来,通过 Row 和 MyText 显示“热门推荐”标题,下面是利用 Grid 组件展示册本的列表。每本册本都利用了 MyGridItemColumn 来天生图文布局。
  1. Row() {
  2.   this.MyText('热门推荐');
  3. }
  4. .height(35)
  5. .width('100%')
  6. // 严选精品(热门推荐)
  7. Grid(this.scroller) {
  8.   GridItem() {
  9.     this.MyGridItemColumn($r('app.media.book6'), '计算机');
  10.   }
  11.   GridItem() {
  12.     this.MyGridItemColumn($r('app.media.book7'), '文学');
  13.   }
  14.   // 更多书籍项...
  15. }
  16. .columnsTemplate('1fr 1fr')  // 设置每行两列
  17. .rowsGap(5)  // 设置行间距
  18. .columnsGap(3)  // 设置列间距
  19. .width('99%')
  20. .height(360)
  21. .margin({
  22.   top: 10
  23. })
  24. .borderRadius(10)
  25. .padding({ left: 3, right: 3 })
  26. .backgroundColor('#ffffff')
复制代码

5.3 册本分类页计划(Page002.ets)

1.总体架构
页面包括:


  • 标题:“图书分类”。
  • Tabs:用于显示差别册本分类的标签,点击标签切换差别分类的册本。
  • 商品列表:每个分类下都有对应的商品列表,展示册本封面、书名、店肆、价格等信息。
  1. @Component
  2. export struct Page002 {
  3.   @State message: string = '图书分类'
  4.   @State fontColor: string = '#182431'
  5.   @State selectedFontColor: string = '#007DFF'
  6.   @State currentIndex: number = 0
  7.   private controller: TabsController = new TabsController()
  8.   // 两个书籍分类的数据
  9.   @State goodsList1: Array<GoodsModel> = [ ... ]
  10.   @State goodsList2: Array<GoodsModel> = [ ... ]
  11. }
复制代码
2.Tab标签页
利用 Tabs 组件来创建四个分类,分别是:“计算机”、“文学”、“励志”和“艺术”。点击差别的标签页可以切换显示差别分类下的册本。
  1. <Tabs({ barPosition: BarPosition.Start, controller: this.controller }) {
  2.   TabContent() {
  3.     this.MyList(this.goodsList1);
  4.   }.tabBar(this.TabBuilder(0, '计算机'))
  5.   TabContent() {
  6.     this.MyList(this.goodsList2);
  7.   }.tabBar(this.TabBuilder(1, '文学'))
  8.   TabContent() {
  9.     this.MyList(this.goodsList1);
  10.   }.tabBar(this.TabBuilder(2, '励志'))
  11.   TabContent() {
  12.     this.MyList(this.goodsList2);
  13.   }.tabBar(this.TabBuilder(3, '艺术'))
  14. }
  15. .barMode(BarMode.Fixed)
  16. .barHeight(48)
  17. .animationDuration(200)
  18. .onChange((index: number) => {
  19.   this.currentIndex = index
  20. })
复制代码
3.自定义组件:TabBuilder, MyText, MyList
TabBuilder方法用于天生每个标签的外观,Text 控件显示分类名称,点击时标签的字体颜色和大小发生厘革。
  1. @Builder
  2. TabBuilder(index: number, name: string) {
  3.   Column() {
  4.     Text(name)
  5.       .fontColor(this.currentIndex === index ? this.selectedFontColor : this.fontColor)
  6.       .fontSize(16)
  7.       .fontWeight(this.currentIndex === index ? 500 : 400)
  8.       .lineHeight(22)
  9.       .margin({ top: 3, bottom: 3 })
  10.     Divider()
  11.       .strokeWidth(2)
  12.       .color('#007DFF')
  13.       .opacity(this.currentIndex === index ? 1 : 0)
  14.   }.width('100%')
  15. }
复制代码
MyList方法用于渲染商品列表,通过 ForEach 遍历册本数据并显示每本书的封面、名称、价格和店肆信息。
  1. @Builder
  2. MyList(list: Array<GoodsModel>) {
  3.   List({ space: 10 }) {
  4.     ForEach(list, (item: GoodsModel, index) => {
  5.       ListItem() {
  6.         Column() {
  7.           Row() {
  8.             Image(item.goodsImage)
  9.               .width(125)
  10.               .height(130)
  11.               .margin({ left: 5 })
  12.               .borderRadius(12)
  13.             Column({ space: 14 }) {
  14.               Text(item.goodsName).width('60%').fontSize(15).fontWeight(FontWeight.Bold)
  15.               Text(item.shopName).fontColor('#787878').fontSize(13)
  16.               Text(item.goodsPrice).fontColor('#ffff0000')
  17.             }
  18.             .alignItems(HorizontalAlign.Start)
  19.             .margin({ left: 10 })
  20.           }
  21.           .width('100%')
  22.           .justifyContent(FlexAlign.Start)
  23.         }
  24.         .borderRadius(8)
  25.         .backgroundColor('#ffffffff')
  26.         .width('96%')
  27.         .height(135)
  28.         .justifyContent(FlexAlign.Center)
  29.         .onClick(() => {
  30.           router.pushUrl({
  31.             url: 'pages/GoodsDetails',
  32.             params: {
  33.               goodsModel: JSON.stringify(item),
  34.             },
  35.           }, router.RouterMode.Single)
  36.         })
  37.       }
  38.     })
  39.   }
  40.   .height('100%')
  41.   .padding({ top: 5 })
  42.   .alignListItem(ListItemAlign.Center)
  43. }
复制代码
4. 页面布局
页面布局中通过 Tabs 和 TabContent 实现了标签切换,每个标签下显示差别的册本分类。标题部分利用了 MyText 来渲染分类标题。
  1. build() {
  2.   Column() {
  3.     Row() {
  4.       this.MyText(this.message);
  5.     }
  6.     .height(35)
  7.     .width('100%')
  8.     Tabs({ barPosition: BarPosition.Start, controller: this.controller }) {
  9.       TabContent() {
  10.         this.MyList(this.goodsList1);
  11.       }.tabBar(this.TabBuilder(0, '计算机'))
  12.       TabContent() {
  13.         this.MyList(this.goodsList2);
  14.       }.tabBar(this.TabBuilder(1, '文学'))
  15.       TabContent() {
  16.         this.MyList(this.goodsList1);
  17.       }.tabBar(this.TabBuilder(2, '励志'))
  18.       TabContent() {
  19.         this.MyList(this.goodsList2);
  20.       }.tabBar(this.TabBuilder(3, '艺术'))
  21.     }
  22.     .vertical(false)
  23.     .barMode(BarMode.Fixed)
  24.     .barWidth('100%')
  25.     .barHeight(48)
  26.     .animationDuration(200)
  27.     .onChange((index: number) => {
  28.       this.currentIndex = index
  29.     })
  30.     .width('100%')
  31.     .backgroundColor('#F1F3F5')
  32.   }
  33.   .backgroundColor('#efefef')
  34.   .width('100%')
  35.   .height('100%')
  36. }
复制代码

5.4 购物车页(Page003.ets)

CardInfo类:


  • 包含购物车商品的信息,属性包括:id、name、image、price、size、numb。
  • 通过构造函数初始化商品信息,包括商品ID、名称、图片、价格和数量。
  1. class CardInfo {
  2.   id: number = 0;
  3.   name: string | Resource = '';
  4.   image: string | Resource | null = null;
  5.   price: number = 0;
  6.   size: string | number = '';
  7.   numb: number = 0;
  8.   constructor(id: number = 0, name: string | Resource = '', image: string | Resource | null = null, price: number, numb: number) {
  9.     this.id = id;
  10.     this.name = name;
  11.     this.image = image;
  12.     this.price = price;
  13.     this.numb = numb;
  14.   }
  15. }
复制代码
Page003布局:


  • shopCardInfo: 存储购物车商品信息,包括两本册本。
  • shopNums: 购物车中商品的总数量。
  • allMoney: 购物车中商品的总价格。
  • numberCount1, numberCount2: 记录每种商品的数量。
  1. @Component
  2. export struct Page003 {
  3.   @State shopCardInfo: Array<CardInfo> = [
  4.     new CardInfo(0, 'Python数据结构与算法分析', $r('app.media.book2'), 26.5, 1),
  5.     new CardInfo(1, '深度学习入门-基于Python的理论与实现', $r('app.media.book1'), 45.5, 2)
  6.   ]
  7.   @State shopNums: number = 0;
  8.   @State allMoney: number = 0;
  9.   @State numberCount1: number = 0
  10.   @State numberCount2: number = 0
  11. }
复制代码
addShopCardInfo方法:


  • 用于增长商品到购物车,更新商品的总价和数量。
  1. addShopCardInfo(price: number, size: number) {
  2.   this.allMoney = this.allMoney + price;
  3.   this.shopNums = this.shopNums + size;
  4. }
复制代码
deleteShopCardInfo方法:


  • 用于淘汰商品,从购物车中移除并更新商品的总价和数量。
  1. deleteShopCardInfo(price: number, size: number) {
  2.   this.allMoney = (this.allMoney - price) <= 0 ? 0 : (this.allMoney - price);
  3.   this.shopNums = (this.shopNums - size) <= 0 ? 0 : (this.shopNums - size);
  4. }
复制代码
购物车展示部分
标题部分:


  • 显示标题“购物车”,字体大小为24px,左边距为12vp。
  1. Column() {
  2.   Text('购物车')
  3.     .fontWeight(FontWeight.Medium)
  4.     .fontSize('24fp')
  5.     .margin({ top: '12vp' })
  6.     .padding({ left: '12vp' })
  7. }
复制代码
商品列表部分:


  • 利用Flex布局,展示购物车商品信息。
  • 每个商品显示商品图片、名称、价格和数量。
  • 通过Checkbox组件控制商品是否选中,选中时增长商品数量,未选中时淘汰商品数量。
  • 商品数量通过Counter组件进行调整,点击加号或减号时更新购物车信息。
  1. Flex({ direction: FlexDirection.Row }) {
  2.   Checkbox({ name: 'checkbox1', group: 'checkboxGroup' })
  3.     .selectedColor('#007DFF')
  4.     .borderRadius('16vp')
  5.     .onChange((value: boolean) => {
  6.       if (value) {
  7.         this.numberCount1++
  8.         this.addShopCardInfo(this.shopCardInfo[0].price, this.shopCardInfo[0].numb);
  9.       } else {
  10.         this.numberCount1--
  11.         this.deleteShopCardInfo(this.shopCardInfo[0].price, this.shopCardInfo[0].numb);
  12.       }
  13.     })
  14.   
  15.   Image(this.shopCardInfo[0].image)
  16.     .objectFit(ImageFit.Cover)
  17.     .width(120)
  18.     .height(118)
  19.     .borderRadius(10)
  20.   Column() {
  21.     Text(this.shopCardInfo[0].name)
  22.       .fontSize('15')
  23.     Row() {
  24.       Text('¥' + this.shopCardInfo[0].price)
  25.         .fontSize(25)
  26.         .fontColor(Color.Red)
  27.         .margin({ top: 20 })
  28.       Counter() {
  29.         Text(this.numberCount1.toString())
  30.       }
  31.       .onInc(() => {
  32.         this.numberCount1++
  33.         this.addShopCardInfo(this.shopCardInfo[0].price, 1)
  34.       })
  35.       .onDec(() => {
  36.         this.numberCount1 = (this.numberCount1--) <= 0 ? 0 : this.numberCount1
  37.         this.deleteShopCardInfo(this.shopCardInfo[0].price, 1)
  38.       })
  39.     }
  40.     .justifyContent(FlexAlign.SpaceBetween)
  41.     .width('100%')
  42.   }
  43.   .padding({ left: 10, top: 10, right: 10 })
  44.   .alignItems(HorizontalAlign.Start)
  45.   .justifyContent(FlexAlign.SpaceBetween)
  46.   .width('100%')
  47.   .height(118)
  48. }
复制代码
结算部分:


  • 显示购物车中已选商品的数量和总价。
  • 提供结算按钮,点击时弹出确认框,展示购物车的总商品数和总金额。
  1. Row() {
  2.   Text('已选' + this.shopNums)
  3.   Text('总计:¥' + this.allMoney).fontColor(Color.Red).padding({ left: '20vp' })
  4.   Button('结算', { type: ButtonType.Normal, stateEffect: true })
  5.     .borderRadius(20)
  6.     .width('40%')
  7.     .height('40vp')
  8.     .fontSize('16fp')
  9.     .fontColor('#ffffffff')
  10.     .fontWeight(FontWeight.Medium)
  11.     .margin({ top: 8 })
  12.     .backgroundColor('#e8483c')
  13.     .onClick(() => {
  14.       AlertDialog.show({
  15.         title: "购物车结算弹窗",
  16.         message: "您一共买了" + this.shopNums + "件商品,总价值:" + this.allMoney + "元。",
  17.         confirm: { value: "确定", action: () => {} }
  18.       })
  19.     })
  20. }
复制代码

5.5 个人信息管理页(Page004.ets)

Page004布局:


  • 页面包含了用户个人信息展示区和常用功能列表。
  • 通过封装的RowItem组件,实现了常用功能项的复用。
RowItem组件:


  • 用于封装每一行的显示内容,包括图标、名称、右侧箭头。
  • 组件接收参数:itemImage、itemName、topValue,用于显示差别功能项。
  • 通过onClick变乱处理点击行为,根据差别的功能项执行相应的操作,如跳转页面或弹出提示。
  1. @Builder
  2. RowItem(
  3.   itemImage: Resource,
  4.   itemName: string,
  5.   topValue: number,
  6. ) {
  7.   Row() {
  8.     Row() {
  9.       Image(itemImage)
  10.         .height(35)
  11.         .width(35)
  12.         .margin({ bottom: 10 })
  13.     }
  14.     Column() {
  15.       Row() {
  16.         Text(itemName)
  17.           .fontWeight(FontWeight.Bold)
  18.           .fontSize(17)
  19.           .margin({ left: 10 })
  20.         Blank()
  21.         Image($r('app.media.rightGo'))
  22.           .height(30)
  23.           .width(40)
  24.       }
  25.       .width('90%')
  26.       .justifyContent(FlexAlign.SpaceBetween)
  27.       Divider()
  28.         .width('90%')
  29.         .margin({ top: 10 })
  30.     }
  31.   }
  32.   .onClick(() => {
  33.     if (itemName == '我的消息') {
  34.       myTools.alertMsg(CommonConstants.UN_DO_TIPS)
  35.     } else if (itemName == '个人中心') {
  36.       router.pushUrl({
  37.         url: 'pages/MyInfo',
  38.       }, router.RouterMode.Single)
  39.     } else if (itemName == '客服') {
  40.       myTools.alertMsg(CommonConstants.UN_DO_TIPS)
  41.     } else if (itemName == '关于我们') {
  42.       myTools.alertMsg(CommonConstants.UN_DO_TIPS)
  43.     } else if (itemName == '邀请好友') {
  44.       myTools.alertMsg(CommonConstants.UN_DO_TIPS)
  45.     }
  46.   })
  47.   .margin({ top: topValue })
  48.   .width('90%')
  49. }
复制代码
个人信息展示部分:


  • 显示用户的头像、昵称和邮箱信息。头像利用圆角结果显示。
  • 通过Column布局将昵称和邮箱信息显示在头像旁边。
  1. Column() {
  2.   Row() {
  3.     Image($r('app.media.touristAvatar'))
  4.       .width(80)
  5.       .height(80)
  6.       .borderRadius(10) // 圆角效果
  7.       .margin({ left: 27 }) // 左边距
  8.   }
  9.   Column() {
  10.     Row() {
  11.       Text("qq").fontSize(25).fontWeight(90).margin({ left: 10 })
  12.     }
  13.     Row() {
  14.       Text("123456789@qq.com")
  15.         .fontSize(14)
  16.         .fontColor('#ff565656')
  17.         .margin({ left: 10 })
  18.     }
  19.     .margin({ top: 8 })
  20.   }
  21.   .alignItems(HorizontalAlign.Start) // 左对齐
  22.   .margin({ left: 12 })
  23. }
复制代码
常用功能区:


  • 通过调用RowItem组件渲染常用功能项,如“我的消息”、“个人中心”、“客服”等。
  • 每个功能项点击后执行差别的操作,部分功能项会弹出提示,部分会跳转到对应页面。
  1. this.RowItem($r("app.media.mymsg"), '我的消息', 10)
  2. this.RowItem($r("app.media.gerenxinxi"), '个人中心', 10)
  3. this.RowItem($r("app.media.aboutus"), '关于我们', 10)
  4. this.RowItem($r("app.media.kefu"), '客服', 10)
  5. this.RowItem($r("app.media.yaoqinghaoyou"), '邀请好友', 10)
复制代码
退出登录部分:


  • 提供退出登录的按钮,点击后弹出确认框,扣问用户是否确定退出。
  • 确定退出后跳转到登录页面。
  1. Button('退出登录', { type: ButtonType.Normal, stateEffect: true })
  2.   .borderRadius(20)
  3.   .width('85%')
  4.   .height(40)
  5.   .margin({ top: 190 })
  6.   .backgroundColor('#e8483c')
  7.   .onClick(() => {
  8.     AlertDialog.show({
  9.       title: "请确认:",
  10.       message: '确定退出APP吗?',
  11.       autoCancel: false,
  12.       alignment: DialogAlignment.Center,
  13.       primaryButton: {
  14.         value: "确定",
  15.         fontColor: Color.Red,
  16.         action: () => {
  17.           router.replaceUrl({
  18.             url: 'pages/Index',
  19.           }, router.RouterMode.Single)
  20.         }
  21.       },
  22.       secondaryButton: {
  23.         value: "取消",
  24.         action: () => {}
  25.       }
  26.     })
  27.   })
复制代码

5.6 页面生命周期管理和数据备份规复

《当当网》应用程序的焦点模块:页面生命周期管理和数据备份规复。
在该项目中,EntryAbility.ets 和 EntryBackupAbility.ets 两个文件负责管理应用程序的页面生命周期以及数据的备份和规复功能。
EntryAbility.ets 文件定义了一个名为 EntryAbility 的类,该类继承自 UIAbility 类,实现了一系列生命周期方法:
  1. // 在页面创建时被调用,可以在此执行一些初始化操作
  2. onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
  3.   hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
  4. }
  5. // 在页面窗口创建时被调用,在这里加载页面内容
  6. onWindowStageCreate(windowStage: window.WindowStage): void {
  7.   hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
  8.   windowStage.loadContent('pages/Index', (err) => {
  9.     if (err.code) {
  10.       hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
  11.       return;
  12.     }
  13.     hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.');
  14.   });
  15. }
复制代码
在 onCreate() 方法中,开发者可以执行一些页面初始化的操作。在 onWindowStageCreate() 方法中,通过调用 windowStage.loadContent() 方法来加载 pages/Index 页面。假如页面加载失败,会记录错误日记。
onDestroy() 方法在页面烧毁时被调用,开发者可以在此释放资源。onWindowStageDestroy() 方法在页面窗口烧毁时被调用。onForeground() 和 onBackground() 方法分别在页面进入前台和后台时被调用。
这些生命周期方法确保了应用程序的页面能够正常加载和烧毁,为用户提供稳定的利用体验。
另一个关键模块 EntryBackupAbility.ets 定义了一个名为 EntryBackupAbility 的类,该类继承自 BackupExtensionAbility 类,实现了数据备份和规复的功能。
  1. // 在需要备份数据时被调用,可以在此实现数据备份逻辑
  2. async onBackup() {
  3.   hilog.info(0x0000, 'testTag', 'onBackup ok');
  4. }
  5. // 在需要从备份中恢复数据时被调用,可以在此实现数据恢复逻辑
  6. async onRestore(bundleVersion: BundleVersion) {
  7.   hilog.info(0x0000, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion));
  8. }
复制代码
onBackup() 方法在需要备份数据时被调用,开发者可以在此实现数据备份的逻辑。onRestore() 方法在需要从备份中规复数据时被调用,开发者可以在此实现数据规复的逻辑。这两个方法都会记录干系操作的日记信息,方便后续题目排查。
通过这个类,应用程序可以可靠地备份和规复用户数据,提高应用程序的结实性和可靠性。在现实开发中,开发者还可以根据应用程序的具体需求,完善备份和规复的具体实现逻辑。
总的来说,EntryAbility 和 EntryBackupAbility 两个类共同构成了该电子商城购书应用程序的焦点功能模块,分别负责管理页面生命周期和提供数据备份规复功能。这些模块的计划确保了应用程序的稳定运行和数据安全性,为用户提供了良好的利用体验。

5.7 体系功能模块

起首包括通用常量模块 (CommonConstants.ets)
  1. export default class CommonConstants {
  2.   /**
  3.    * 相关功能
  4.    */
  5. }
复制代码
用于存放应用程序中的通用常量,进行集中管理。
其次是体系工具模块 (MyTools.ets)
  1. import promptAction from '@ohos.promptAction';
  2. /*
  3. * Desc: 系统工具类
  4. */
  5. export class MyTools {
  6.   /**
  7.    * 弹框提示
  8.    * @param message
  9.    */
  10.   alertMsg(message: string) {
  11.     promptAction.showToast({
  12.       message: message, //message属性用于设置提示信息
  13.       duration: 2000, //duration属性用于设置提示信息停留时长,单位为毫秒,取值范围是[1500,10000]
  14.       bottom: '360vp' //bottom属性用于设置提示信息到底部的距离
  15.     })
  16.   }
  17. }
  18. export const myTools = new MyTools();
复制代码
该类提供了一些常用的体系工具方法,调用了 promptAction.showToast() API,向用户屏幕底部显示一个连续2秒的提示信息。这个方法可以方便地在应用程序的任何地方被调用,以向用户提供反馈信息。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

立山

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表