【HarmonyOS】体验鸿蒙电商平台的未来之旅!

news2024/11/16 12:57:23

           从今天开始,博主将开设一门新的专栏用来讲解市面上比较热门的技术 “鸿蒙开发”,对于刚接触这项技术的小伙伴在学习鸿蒙开发之前,有必要先了解一下鸿蒙,从你的角度来讲,你认为什么是鸿蒙呢?它出现的意义又是什么?鸿蒙仅仅是一个手机操作系统吗?它的出现能够和Android和IOS三分天下吗?它未来的潜力能否制霸整个手机市场呢?

今天实现一个简单的小案例,从零开始讲解如何通过鸿蒙开发实现一个电商平台的案例。

目录

新建项目

登录页面

点击登录

个人中心

首页搭建

Tabs组件


新建项目

首先我们先打开DevEco Studio,点击新建项目:

然后根据自己的情况选择应用,这里我们选择空的 Empty Ability 进行创建:

然后接下来输入自己的项目名称就行,点击finish即可:

运行本地预览器,可以看到我们的初始项目已经跑通:

登录页面

登录页面的构建很简单,我们参考网上的登录页面,简单的构建一下登录页面的画面,这里我使用的图标都是来自阿里云图标库当中,大家可以根据自己的情况在网上寻找资源来构建画面,闲话少说我们直接开始,首先我们在pages文件夹下新建arkts文件Login文件,当作是我们的登录页面,接下来我们开始正式编写相关代码:

因为构建静态页面很简单,也没有什么好讲的,这里我就将静态页面的源代码直接共享出来吧,大家可以自己看一下:

// 登录页面

// 文本框样式
@Extend(TextInput) function InputStyle() {
  .placeholderColor('#ff5d7e9d')
  .height(60)
  .fontSize(20)
  .backgroundColor('#ccc')
  .width('90%')
  .padding({ left: 15 })
  .maxLength(10)
}

// 分割线
@Extend(Line) function liseStyle() {
  .width('100%')
  .height(2)
  .backgroundColor('#efefef')
  .margin({ top: 10, bottom: 10 })
}

// Text组件的蓝色文本样式
@Extend(Text) function blueTextStyle() {
  .fontColor('#ff084d85')
  .fontSize(15)
  .fontWeight(FontWeight.Bold)
}

@Entry
@Component
struct Login {
  @State account: string = '' // 登录账号
  @State password: string = '' // 登录密码
  @State isShowProgress: boolean = true // 是否显示登录的进度条
  // 构建登录按钮
  @Builder imageButton(image: Resource) {
    // 构建按钮图片,本质上就是在按钮里面增加一个image组件
    Button({ type: ButtonType.Circle, stateEffect: true }){ // 圆形按钮,按下按钮有切换颜色效果
      Image(image)
    }
    .height(50).width(50).backgroundColor('#fff')
  }

  build() {
    Column() { // 登录界面的布局
      Image($r('app.media.login_logo')) // Logo图片
        .width($r('app.float.logo_image_size'))
        .height($r('app.float.logo_image_size'))
        .margin({
          top: $r('app.float.logo_margin_top'),
          bottom: $r('app.float.logo_margin_bottom')
        })

      // 登录标题
      Text($r('app.string.login_page'))
        .fontSize($r('app.float.page_title_text_size'))
        .fontWeight(FontWeight.Medium)
        .fontColor($r('app.color.page_title_text_color'))

      // 小标题
      Text('登录账号以获取更多服务')
        .fontSize(20)
        .fontColor('#ccc')
        .margin({ top: 15, bottom: 25 })

      // 账号输入框
      TextInput({ placeholder: '请输入账号' })
        .InputStyle()
        .type(InputType.Number) // 文本行中只能输入数字
        .onChange((value: string) => {
          this.account = value
        })
      Line()
        .liseStyle()
      // 密码输入框
      TextInput({ placeholder: '请输入密码' })
        .InputStyle()
        .type(InputType.Password)
        .onChange((value: string) => {
          this.password = value
        })
      Line()
        .liseStyle()

      // 短信提示与验证码
      Row(){
        Text('短信验证码登录').blueTextStyle()
        Text('忘记密码').blueTextStyle()
      }
      .width('100%')
      .justifyContent(FlexAlign.SpaceBetween)
      .padding({ left: 12, right: 12 })

      // 登录按钮
      Button('登录', { type: ButtonType.Capsule })
        .width('75%')
        .height(45)
        .fontSize(20)
        .fontWeight(FontWeight.Bold)
        .margin({ top: 60, bottom: 20 })
        .onClick(() => {
          // 登录事件
        })

      // 注册账号文本
      Text('注册账号')
        .fontColor('blue').fontSize(15).fontWeight(FontWeight.Medium)

      // 是否显示进度条
      if (this.isShowProgress){
        LoadingProgress()
          .color('red').width(40).height(40).margin({ top: 10 })
      }

      // 其他方式登录
      Text('其他方式登录').fontColor('#ff776f6f').fontSize(18)
        .fontWeight(FontWeight.Medium).margin({ top: 5, bottom: 10 })

      // 三种登录方式
      Row({ space: 40 }){
        this.imageButton($r("app.media.wx"))
        this.imageButton($r("app.media.tb"))
        this.imageButton($r('app.media.qq'))
      }
    }
    .width('100%')
    .height('100%')
  }
}

最终呈现的效果如下:

关于这个静态页面的构建我简单提一下,对于公共常用的样式,我们可以将其书写在静态资源base当中然后进行调用即可,上文的代码我进行了简单的使用,主要的方式如下:

点击登录

接下来我们给我们静态页面的登录按钮设置点击事件进行登录操作,以及对进度条的显示进行一个设置,当点击登录和进入到正式页面之间的间隔中进行显示这个进度条出来,闲话少说正式开始:

@State isShowProgress: boolean = false // 是否显示登录的进度条
private timeOutId: number = -1 // 控制登录超时的时间变量

// 登录回调事件
Login(): void {
  if(this.account === '' || this.password === ''){
    promptAction.showToast({ // 开启一个确认弹层
      message: '账号密码为空,请重新输入!'
    })
  } else {
    this.isShowProgress = true
    if(this.timeOutId == -1) {
      this.timeOutId = setTimeout(() => {
        // 2秒之后执行的函数
        this.isShowProgress = false
        this.timeOutId = -1
        // 页面跳转
      }, 2000)
    }
  }
}

然后我们在离开页面的时候,对定时器进行一个清除:

// 离开页面要取消定时器
aboutToDisappear() {
  clearTimeout(this.timeOutId)
  this.timeOutId = -1
}

实现的效果如下:

接下来我们开始实现点击登录按钮后,触发点击事件进行页面的路由跳转,代码如下,关于个人中心页面的搭建,可以继续看下一个标题的内容:

个人中心

接下来开始实现个人中心的页面,个人中心的页面搭建其实也非常简单,这里我们把要存放的图片和相关标题的内容单独抽离出去,形成一个新的类,来获取静态资源,后面需求页面要使用的时候直接调用就可以了,具体代码如下:

interface ItemData {
  title: string;
  imagePath: Resource;
  switch?: boolean;
}

export class DataModel {
  // 获取列表数据
  getSettingListData(): ItemData[] {
    let settingListData: ItemData[] = [
      {
        title: '推送通知',
        imagePath: $r('app.media.1'),
        switch: true,
      },
      {
        title: '数据管理',
        imagePath: $r('app.media.2'),
        switch: false,
      },
      {
        title: '菜单设置',
        imagePath: $r('app.media.3'),
        switch: false,
      },
      {
        title: '关于个人',
        imagePath: $r('app.media.4'),
        switch: false,
      },
      {
        title: '清除缓存',
        imagePath: $r('app.media.5'),
        switch: false,
      },
      {
        title: '隐私协议',
        imagePath: $r('app.media.6'),
        switch: false,
      },
    ];
    return settingListData;
  }
}

export default new DataModel();

关于这些静态资源的图片可以到阿里云图标库上寻找,这里就不再赘述了:

然后接下来我们需要开始正式的书写我们的个人中心页面的代码了,具体静态页面代码如下:

import router from '@ohos.router'
import DataModel from '../../components/DataModel'
import promptAction from '@ohos.promptAction'

// 设置界面
@Entry
@Component
struct MySettings {
  @State account: number = 0

  onPageShow(){
    let acc = router.getParams() as Record<string, number>
    if (acc) {
      this.account = acc['sendMsg']
    }
  }

  // 构建设置单元格函数
  @Builder settingCell(item) {
    Row(){
      Row({ space: 10 }) {
        Image(item.imagePath).width(38).height(38)
        Text(item.title).fontSize(25)
      }
      // 判断switch是否为true
      if(!item.switch) {
        Image($r('app.media.arrow_right')).width(30).height(30)
      } else {
        Toggle({ type: ToggleType.Switch, isOn: false }) // 显示一个开关组件
      }
    }
    .justifyContent(FlexAlign.SpaceBetween)
    .width('100%')
    .padding({ left: 15, right: 15 })
  }

  build() {
    Scroll(){
      Column({ space: 12 }){
        Column(){ // 创建一个内嵌的列布局
          Text('个人中心').fontWeight(FontWeight.Bold).fontSize(40)
            .margin({ top: 10 }).padding({ left: 15 })
        }
        .width('100%')
        .alignItems(HorizontalAlign.Start)

        // 账户布局
        Row(){
          Image($r('app.media.account')).width(60).height(60)
          Column(){
            Text('张三').fontSize(25)
            Text(`${this.account.toString()}@163.com`).fontSize(15).margin({ top: 8 })
          }
          .layoutWeight(2)
          .alignItems(HorizontalAlign.Start)
          .margin({ left: 30 })
        }
        .width('100%')
        .height(70)
        .backgroundColor(Color.White)
        .padding({ left: 20, right: 20 })
        .borderRadius(20)
        .margin({ top: 30 }).alignItems(VerticalAlign.Center)

        // 列表布局
        List(){
          ForEach(DataModel.getSettingListData(), (item, index) => {
            ListItem(){
              this.settingCell(item)
            }
            .onClick(() => {
              promptAction.showDialog({
                message: `第${index + 1}功能:${item.title},还未完成,尽情期待!`
              })
            })
            .height(60)
          })
        }
        .backgroundColor(Color.White)
        .width('100%')
        .divider({
          strokeWidth: 1, // 设置分割线的高度
          color: Color.Gray, // 设置分割线的颜色
          startMargin: 15, // 设分割线的起始边距
          endMargin: 15 // 设置分割线的结束边距
        })
        .borderRadius(30)
        .padding({ top: 15, bottom: 20 })

        Blank()

        // 退出按钮的布局
        Button('退出登录', { type: ButtonType.Capsule })
          .width('90%').height(50).fontSize(20).fontColor('red')
          .backgroundColor('#ccc').margin({ bottom: 15 })
      }
      .height('100%')
    }
    .width('100%')
    .height('100%')
  }
}

呈现的效果如下所示:

然后接下来我们给退出登录的按钮设置点击事件:

首页搭建

接下来开始实现首页的页面搭建,静态页面的搭建其实很简单,博主也没有什么好讲的说实话,无非就是Grid布局以及Swiper布局的排版一下注意一点就可以了,ok接下来我们开始给出具体代码吧:

import DataModel from '../../components/DataModel'

// 首页
@Entry
@Component
struct Home {
  private swiperController: SwiperController = new SwiperController() // 轮播控制器实例

  build() {
    Scroll(){
      Column({ space: 10 }){
        Column(){ // 标题
          Text('首页').fontWeight(FontWeight.Bold).fontSize(30)
            .margin({ top: 10 }).padding({ left: 10 })
        }
        .width('100%').alignItems(HorizontalAlign.Start)

        // 轮播图片
        Swiper(this.swiperController){
          ForEach(DataModel.getSwiperImage(), (item) => {
            // 构建每一张图片
            Image(item.imagePath)
              .width('100%')
              .height(250)
              .borderRadius(50)
          })
        }
        .autoPlay(true) // 轮播图自动播放
        .margin({ top: 15 })

        // 菜单列表
        Grid(){
          ForEach(DataModel.getFirstGridData(), (item) => {
            GridItem(){
              Column(){
                Image(item.imagePath).width(40).height(40)
                Text(item.title).fontSize(15).margin({ top: 5 })
              }
            }
          })
        }
        .columnsTemplate('1fr 1fr 1fr 1fr') // 设置网格的列模板,每列平分空间
        .rowsTemplate('1fr 1fr') // 设置网格的行模板,每行平分空间
        .columnsGap(10)
        .rowsGap(10)
        .padding({ top: 10, bottom: 10 })
        .height(200)
        .backgroundColor(Color.White)
        .borderRadius(50)

        // 频道列表
        Text('列表').fontSize(20).fontWeight(FontWeight.Bold).width('100%')
          .margin({ top: 15 })
        Grid(){
          ForEach(DataModel.getSecondGridData(), (item) => {
            GridItem() {
              Column() {
                Text(item.title).fontSize(20).fontWeight(FontWeight.Medium)
                Text(item.describe).fontSize(15).fontColor('#ccc').margin({ top: 5 })
              }
              .alignItems(HorizontalAlign.Start) // 两个文本框在水平方向居左对齐
            }
            .padding({ top: 15, left: 10 }).borderRadius(10)
            .align(Alignment.TopStart) // 设置网格项对齐方式为顶部对齐
            .backgroundImage(item.imagePath) // 设置网格项背景图像
            .backgroundImageSize(ImageSize.Cover) // 设置背景图像尺寸模式为覆盖
            .width('100%').height('100%')
          })
        }
        .width('100%').height(300)
        .columnsTemplate('1fr 1fr').rowsTemplate('1fr 1fr') // 设置网格的行列模板
        .columnsGap(10).rowsGap(10).margin({ bottom: 15 })
      }
    }
    .height('100%')
  }
}

最终呈现的效果如下:

Tabs组件

ArkUI开发框架提供了一种页签容器标签Tabs,开发者通过Tabs组件可以很容易的实现内容视图的切换。页签容器 Tabs 的形式多种多样,不同的页面设计页签不一样,可以把页签设置在底部、顶部或者侧边。

接下来我们创建页面组件index,然后在页面组件当中书写tab页面:

import Home from './Home'
import MySettings from './MySettings'
import router from '@ohos.router'

// app主页,页面组件
@Entry
@Component
struct Index {
  @State currentIndex: number = 0 // 当前默认的页签索引号
  private account: number
  private tabsController: TabsController = new TabsController()

  // 接收路由参数
  onPageShow(){
    let acc = router.getParams() as Record<string, number>
    if (acc) {
      this.account = acc['sendMsg']
    }
  }

  // 自定义Tabs函数
  @Builder TabBuilder(title: string, index: number, selectedImg: Resource, normalImg: Resource) {
    Column() {
      Image(this.currentIndex == index ? selectedImg : normalImg)
        .width(30).height(30)
      Text(title).margin({ top: 5 }).fontSize(15)
        .fontColor(this.currentIndex == index ? '#008c8c' : '#ccc')
    }
    .justifyContent(FlexAlign.Center)
    .width('100%').height('50')
    .onClick(() => {
      this.currentIndex = index
      this.tabsController.changeIndex(this.currentIndex) // 修改页签的索引
    })
  }
  build() {
    Tabs({
      barPosition: BarPosition.End, // 页签底部展示
      controller: this.tabsController // 页签容器的控制
    }){ // 标签容器
      // 首页
      TabContent(){
        Home()
      }
      .padding({ left: 20, right: 20 }).backgroundColor('#ccc')
      .tabBar(this.TabBuilder('首页', 0, $r('app.media.home_active'), $r('app.media.home')))
      // 个人中心
      TabContent(){
        MySettings({ account: this.account })
      }
      .padding({ left: 20, right: 20 }).backgroundColor('#ccc')
      .tabBar(this.TabBuilder('我的', 1, $r('app.media.my_active'), $r('app.media.my')))
    }
    .animationDuration(0) // 去掉切换页面的动画效果
    .scrollable(false) // 去掉滑动效果,只能点击按钮切换界面
    .width('100%')
    .backgroundColor(Color.White)
    .barHeight(50)
    .barMode(BarMode.Fixed)
  }
}

这里我们需要将之前的Home页面以及MySettings页面进行一个暴露出去:

这里简单提一下,当用户点击登录按钮之后,这里我们需要跳转到index页面的,所以携带的路由参数也是先传递给index页面,然后index页面再传递给子组件MySettings组件当中,这里注意一下:

最终呈现的效果如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1402672.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

点燃航天热情,莞港澳青少年航天研学冬令营收获满满

为进一步促进港澳青少年深度了解祖国的最新发展&#xff0c;通过亲身体验增加对祖国的认识&#xff0c;增强对祖国的向心力。“筑梦航天&#xff0c;行进湾区”莞港澳青少年交流实践活动收官之作“航天研学冬令营”于1月20日在东莞成功举办。来自香港、澳门、广州、深圳、东莞各…

AI 欺诈事件频出,如何重塑身份认证的安全性?

据报告表示&#xff0c;生成式人工智能每年可为世界经济注入相当于 4.4 万亿美元的资金。预计到 2030 年&#xff0c;人工智能对全球财政的潜在贡献将达到 15.7 万亿美元。人们惊叹于 AI 强大工作效率&#xff0c;期待能帮忙节省不必要的劳动力&#xff0c;但事实上 AI 出现之后…

216. 组合总和 III - 力扣(LeetCode)

题目描述 找出所有相加之和为 n 的 k 个数的组合&#xff0c;且满足下列条件&#xff1a; 只使用数字1到9每个数字 最多使用一次 返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次&#xff0c;组合可以以任何顺序返回。 输入示例 k 3, n 7输出示例 [[1,2,…

Allegro如何导入芯片的Pin Delay?

Allegro在做等长时,需要导入芯片的Pin Delay才能做真正的等长。因为有些芯片内部的引脚本身就是不等长的,例如海思的部分芯片。 那么如何导入芯片的Pin Delay呢? 1、打开约束管理器,点击Properties(属性)→Component(器件)→Pin Properties→General。 在右栏找到芯片U1,…

【Linux】第三十二站:命名管道

文章目录 一、命名管道介绍二、编码1.mkfifo2.unlink3.一个简单的例子4.修改 一、命名管道介绍 管道应用的一个限制就是只能在具有共同祖先&#xff08;具有亲缘关系&#xff09;的进程间通信。 如果我们想在不相关的进程之间交换数据&#xff0c;可以使用FIFO文件来做这项工作…

opencv009 滤波器01(卷积)

图像卷积操作&#xff08;convolution&#xff09;&#xff0c;或称为核操作&#xff08;kernel&#xff09;&#xff0c;是进行图像处理的一种常用手段&#xff0c; 图像卷积操作的目的是利用像素点和其邻域像素之前的空间关系&#xff0c;通过加权求和的操作&#xff0c;实现…

【服务器】Xshell与Xftp软件的使用指南

目录 【Xshell软件】 1.1 Xshell软件的功能 1.2 Xshell软件的使用 【Xftp软件】 2.1 Xftp软件的功能 2.2 Xftp软件的使用 可替代产品【FinalShell】 3.1 FinalShell软件的使用 3.2 FinalShell连接服务器失败解决方法 可替代产品【FileZilla】

VSCode无法下载插件,提示 Error while fetching extensions : XHR failed

解决方案&#xff1a; 打开vscode&#xff0c;依次点击File->Preferences->settings&#xff0c;中文就是文件->首选项->设置&#xff0c;打开如下图&#xff1a; 我们去搜索&#xff1a;Proxy &#xff0c; 然后回车 最重要的一步&#xff1a;将Http Prox…

关于 open ai,你了解多少?

OpenAI 的历史 第一阶段&#xff1a;2015-2018 年 2015 年&#xff0c;埃隆马斯克、山姆阿尔特曼、彼得蒂尔和杰西卡利文斯顿联合创立了 OpenAI。OpenAI 的目标是开发安全、有益的 AGI&#xff0c;并确保其造福全人类。在这一阶段&#xff0c;OpenAI 主要专注于基础研究&…

微信公众号怎么申请超过2个

一般可以申请多少个公众号&#xff1f;目前公众号申请数量的规定是从2018年底开始实施的&#xff0c;至今没有变化。规定如下&#xff1a;1、个人可以申请1个个人主体的公众号&#xff1b;2、企业&#xff08;有限公司&#xff09;可以申请2个公众号&#xff1b;3、个体户可以申…

中仕教育:2024年国考面试题型有哪些?

国考面试是选拔公务员的重要环节&#xff0c;通常涉及以下几个方面&#xff1a; 1. 自我介绍&#xff1a;考官通常会要求考生做一个简短的自我介绍。内容可以包括自己的基本情况、学历、工作经历等。 2. 专业知识&#xff1a;根据应聘者所应聘的职位和部门的不同&#xff0c;…

猛玛LARK M1无线麦克风采用 思远半导体 其实就是蓝牙话筒

自上世纪无线电技术开始发展起来&#xff0c;到了几十年后的今天&#xff0c;无线通讯技术已经成熟&#xff0c;开始追求更好的音质以及用户使用体验&#xff0c;优秀的产品也如雨后春笋般的出现&#xff0c;技术革新&#xff0c;极致音质&#xff0c;竞争也越来越激烈。这时候…

VC++中使用OpenCV进行人脸检测

VC中使用OpenCV进行人脸检测 对于上面的图像&#xff0c;如何使用OpenCV进行人脸检测呢&#xff1f; 使用OpenCV进行人脸检测十分简单&#xff0c;OpenCV官网给了一个Python人脸检测的示例程序&#xff0c; objectDetection.py代码如下&#xff1a; from __future__ import p…

【架构师视角系列】Apollo配置中心之Client端(二)

原创文章&#xff0c;转载请标注。https://blog.csdn.net/leeboyce/article/details/135733075 文章目录 声明配置中心系列文章一、客户端架构1、Config Service职责&#xff08;1&#xff09;配置管理&#xff08;2&#xff09;配置发布&#xff08;3&#xff09;配置读取 2、…

【Linux】Linux开发工具 - vim的基本操作

IDE例子 Linux编辑器-vim使用 vi/vim的区别简单点来说&#xff0c;它们都是多模式编辑器&#xff0c;不同的是vim是vi的升级版本&#xff0c;它不仅兼容vi的所有指令&#xff0c;而且还有一些新的特性在里面。例如语法加亮&#xff0c;可视化操作不仅可以在终端运行&#xff…

暴力破解常见的服务器

目录 使用 pydictor 生成自己的字典工具liunx下载使用常用的参数说明插件型字典 (可自己根据 API 文档开发) 使用 hydra 工具在线破解系统用户密码使用 hydra 破解 windows 7 远程桌面密码使用 hydra 工具破解 ssh 服务 root 用户密码 使用 Medusa 工具在线破解medusa参数说明M…

公网环境调试本地配置的Java支付宝沙箱环境模拟支付场景

文章目录 前言1. 下载当面付demo2. 修改配置文件3. 打包成web服务4. 局域网测试5. 内网穿透6. 测试公网访问7. 配置二级子域名8. 测试使用固定二级子域名访问 前言 在沙箱环境调试支付SDK的时候&#xff0c;往往沙箱环境部署在本地&#xff0c;局限性大&#xff0c;在沙箱环境…

JVM知识总结

1.概述 JVM指的是Java虚拟机&#xff0c;本质上是一个运行在计算机上的程序&#xff0c;他的职责是运行Java字节码文件&#xff0c;作用是为了支持跨平台特性。 功能&#xff1a; 装载字节码&#xff0c;解释/编译为机器码 管理数据存储和垃圾回收 优化热点代码提升效率 …

AI技术图像编辑 Luminar Neo

Luminar Neo是一款先进的AI照片编辑软件&#xff0c;旨在简化和增强照片编辑过程。它适用于macOS和Windows&#xff0c;提供独立的应用程序以及用于集成到现有工作流程的插件。Luminar Neo的主要特点包括AI天空替换、Accent AI、氛围AI以及20多种独特的照片效果。无论是风景摄影…

Qt事件处理,提升组件类

1.相关说明 1.提升组件QLabel的类&#xff0c;以实现双击功能 2.监控键盘事件&#xff0c;实现上下左右移动 3.鼠标点击获取坐标 2.相关界面 3.相关代码和操作 自定义类TMyLabel&#xff0c;父类为QLabel tmylabel.h #ifndef TMYLABEL_H #define TMYLABEL_H #include <QL…