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

HarmonyOs 应用基础--ArkTS-核心-基础

目录

八. ArkTS-语句-类型进阶与渲染控制

1. 对象进阶

1.1. 定义对象数组

1.2. 使用对象数组

2. 渲染控制 - ForEach

2.1. ForEach语法

 2.2. ForEach使用优化代码

 2.3. 案例-学生档案

实现思路

3. Math对象

 4. 综合案例 -- 抽奖卡案例

4.1. 初始页面布局(静态)

4.2. 根据数据渲染初始页面

4.2.1. 准备响应数据

4.2.2. 渲染初始页面

4.3. 遮罩层静态布局

4.4. 遮罩层动态交互

4.4.1. 按钮交互

4.4.2. 图片数据

4.5. 中奖结果

 4.5.1. 抽奖静态页面

4.5.2. 条件渲染-抽卡与抽奖页面

4.5.3. 抽奖数据处理

4.6. 再次抽奖


八. ArkTS-语句-类型进阶与渲染控制

今日核心

  1. 对象
  2. 渲染控制ForEach

1. 对象进阶

1.1. 定义对象数组

// 1. 定义接口
interface Person {
  stuId: number
  name: string
  gender: string
  age: number
}

// 2. 根据接口定义对象数组
let students: Person[] = [
  {stuId: 1, name: '小红', gender: '女', age: 18},
  {stuId: 2, name: '小明', gender: '男', age: 19},
  {stuId: 3, name: '大强', gender: '男', age: 18}
]

1.2. 使用对象数组

  • 访问某一个对象:
    • 每一对象在数组中都是有对应的下标的, 可以通过 数组名[下标] 访问
  • 访问某一对象的某一个属性
    • 先找到要访问的对象, 在该对象的属性访问属性 数组名[下标].属性名 访问
  • 依次访问每一个对象
    • for ... of 进行访问即可
// 3. 访问属性 数组名[下标].属性名
console.log('小红的年龄是', students[0].age)

// 4. 遍历对象数组
for (const item of students) {
  console.log('学生姓名是', item.name)
}

2. 渲染控制 - ForEach

当我们页面中的区域中有多个样式相同的小区域,只有内容数据不一样的时候, 为了提升代码的复用率,不需要一个一个的编写UI组件,我们可以将所有的数据整合成一个数组, 并采取ForEach进行循环渲染.如下图区域,如果我们分别实现每个栏目,代码太过于冗余,这时就可以使用ForEach进行渲染了

2.1. ForEach语法

ForEach基于数组类型数据来进行循环渲染,需要与容器组件配合使用,且接口返回的组件应当是允许包含在ForEach父容器组件中的子组件。

  • 语法: ForEach(arr, (item, index) => {})

参数

参数类型

是否必须

参数说明

arr

Array

数据源, 根据该数组生成对应的UI组件渲染到页面中:

  • 可以为空数组

UI组件生成函数

(item: any, index?: number) => void

UI组件生成函数

  • 为数组中的每个元素创建对应的组件
  • item: 代表每一个数组元素, 类型与数组元素保持一致,不可以省略
  • index: 代表每一个数组元素的下标,可以省略

 2.2. ForEach使用优化代码


@Entry
  @Component
  struct Index {
    build() {
      Column(){
        Text('电子产品')
          .fontSize('24')
          .fontWeight(700)
          .fontColor(Color.Orange)
          .width('100%')
          .padding(15)
        Text('精品服饰')
          .fontSize('24')
          .fontWeight(700)
          .fontColor(Color.Orange)
          .width('100%')
          .padding(15)
        Text('母婴产品')
          .fontSize('24')
          .fontWeight(700)
          .fontColor(Color.Orange)
          .width('100%')
          .padding(15)
        Text('影音娱乐')
          .fontSize('24')
          .fontWeight(700)
          .fontColor(Color.Orange)
          .width('100%')
          .padding(15)
        Text('海外旅游')
          .fontSize('24')
          .fontWeight(700)
          .fontColor(Color.Orange)
          .width('100%')
          .padding(15)
      }
      .width('100%')
        .height('100%')
    }
  }

 完成代码

@Entry
  @Component
  struct Index {
    @State
    titles:string[] = ['电子产品', '精品服饰', '母婴产品', '影音娱乐', '海外旅游']

    build() {
      Column() {
        ForEach(this.titles, (item: string, index: number) => {
          Text(item)
            .fontSize('24')
            .fontWeight(700)
            .fontColor(Color.Orange)
            .width('100%')
            .padding(15)
        })
      }
    }
  }

 2.3. 案例-学生档案

模版代码 

@Entry
@Component
struct Index {

  build() {
    Column() {
      Row() {
        Text(`姓名:张三,年龄:18`)
          .fontSize(18)
          .fontColor('#fff')
        Button('年龄+1')
          .backgroundColor('#e64133')
      }
      .width('100%')
      .height(60)
      .backgroundColor(Color.Orange)
      .borderRadius(5)
      .padding({left: 10, right: 10})
      .margin({bottom: 10})
      .justifyContent(FlexAlign.SpaceBetween)
    }
      .padding(20)
  }
}
实现思路
  • 准备数据
    • 定义数组元素接口
    • 根据接口创建对象数组保存数据
  • ForEach循环渲染
    • 使用数组元素的属性(item.属性名)动态填充UI组件对应的位置
interface Person {
  stuId: number
  name: string
  gender: string
  age: number
}

@Entry
@Component
struct Index {
  @State
  students: Person[] = [
    {stuId: 1, name: '小红', gender: '女', age: 18},
    {stuId: 2, name: '小明', gender: '男', age: 19},
    {stuId: 3, name: '大强', gender: '男', age: 18}
  ]

  build() {
    Column() {
        ForEach(this.students, (item: Person, index: number) => {
            Row() {
              Text(`姓名:${item.name},年龄:${item.age}`)
                .fontSize(18)
                .fontColor('#fff')
              Button('年龄+1')
                .backgroundColor('#e64133')
                .onClick(() => {
                  // item.age += 1
                  this.students[index] = {
                    stuId: item.stuId,
                    name: item.name,
                    gender: item.gender,
                    age: item.age += 1
                  }
                })
            }
            .width('100%')
            .height(60)
            .backgroundColor(Color.Orange)
            .borderRadius(5)
            .padding({left: 10, right: 10})
            .margin({bottom: 10})
            .justifyContent(FlexAlign.SpaceBetween)
        })
    }
    .padding(20)
  }
}

3. Math对象

Math 是一个内置对象,它拥有一些数学常数属性和数学函数方法, Math 用于 Number 类型数据的处理.

Math.random()

  • 随机数
  • 取值范围 [0, 1)之间的随机小数,左闭右开, 可以取到0,但是取不到1

Math.ceil()

  • 需要一个数字形参数
  • 总是向上取整

Math.floor()

  • 需要一个数字形参数
  • 总是向下取整
  • 代码测试
// 1. 随机数
console.log('Math对象', Math.random())  // 0-1 之间的随机小数

// 2. 向上取整
console.log('Math对象', Math.ceil(1.1))  // 2
console.log('Math对象', Math.ceil(1.9))  // 2

// 3. 向下取整
console.log('Math对象', Math.floor(1.1))  // 1
console.log('Math对象', Math.floor(1.9))  // 1
  • 求0--10之间的随机整数
// 0-10 之间的随机数
console.log('Math对象', Math.random() * 11)

// 0-10 之间的随机 整数
console.log('Math对象', Math.floor(Math.random() * 11))

 4. 综合案例 -- 抽奖卡案例

实现如下图所示的效果 

4.1. 初始页面布局(静态)

备注:无数据

@Entry
@Component
struct Index {

  build() {
    Column() {
      // 一. 初始界面
      Column() {
        // 图片区域
        Flex({wrap: FlexWrap.Wrap}) {
          Badge({
            count: 1,
            style: {badgeSize: 16, badgeColor: '#f00', fontSize: 14}
          }) {
            Image($r('app.media.bg_00'))
              .width(80)
          }
          .margin(15)
          Badge({
            count: 1,
            style: {badgeSize: 16, badgeColor: '#f00', fontSize: 14}
          }) {
            Image($r('app.media.bg_00'))
              .width(80)
          }
          .margin(15)
          Badge({
            count: 1,
            style: {badgeSize: 16, badgeColor: '#f00', fontSize: 14}
          }) {
            Image($r('app.media.bg_00'))
              .width(80)
          }
          .margin(15)
          Badge({
            count: 1,
            style: {badgeSize: 16, badgeColor: '#f00', fontSize: 14}
          }) {
            Image($r('app.media.bg_00'))
              .width(80)
          }
          .margin(15)
          Badge({
            count: 1,
            style: {badgeSize: 16, badgeColor: '#f00', fontSize: 14}
          }) {
            Image($r('app.media.bg_00'))
              .width(80)
          }
          .margin(15)
          Badge({
            count: 0,
            style: {badgeSize: 16, badgeColor: '#f00', fontSize: 14}
          }) {
            Image($r('app.media.bg_00'))
              .width(80)
          }
          .margin(15)
        }
        .margin({top: 100, bottom: 50})
        .padding({left: 15})
        // 抽卡按钮
        Button('立即抽卡')
          .width(200)
          .backgroundColor('#ED5B8C')
          .stateStyles({
            pressed: {
              .backgroundColor('#EA446C')
            }
          })
          .animation({
            duration: 1000
          })
      }
    }
  }
}

4.2. 根据数据渲染初始页面

4.2.1. 准备响应数据

思路: 观察效果可以发现列表区域的每一项, 至少需要两个数据:

  1. 图片的地址
  2. 抽中的数量
// 初始界面卡片接口
interface Card {
  url: string
  num: number
}

// 初始界面卡片状态
  @State
  images: Card[] = [
    {url: 'app.media.bg_00', num: 0},
    {url: 'app.media.bg_01', num: 0},
    {url: 'app.media.bg_02', num: 0},
    {url: 'app.media.bg_03', num: 0},
    {url: 'app.media.bg_04', num: 0},
    {url: 'app.media.bg_05', num: 0}
  ]
4.2.2. 渲染初始页面

ForEach() 渲染 Badge组件

// 初始界面卡片接口
interface Card {
  url: string
  num: number
}

@Entry
@Component
struct Index {
  // 初始界面卡片状态
  @State
  images: Card[] = [
    {url: 'app.media.bg_00', num: 0},
    {url: 'app.media.bg_01', num: 0},
    {url: 'app.media.bg_02', num: 0},
    {url: 'app.media.bg_03', num: 0},
    {url: 'app.media.bg_04', num: 0},
    {url: 'app.media.bg_05', num: 0}
  ]

  build() {
    Column() {
      // 一. 初始界面
      Column() {
        // 图片区域
        Flex({wrap: FlexWrap.Wrap}) {
          ForEach(this.images, (item: Card, index: number) => {
            Badge({
              count: item.num,
              style: {badgeSize: 16, badgeColor: '#f00', fontSize: 14}
            }) {
              Image($r(`${item.url}`))
                .width(80)
            }
            .margin(15)
          })
        }
        .margin({top: 100, bottom: 50})
        .padding({left: 15})
        // 抽卡按钮
        Button('立即抽卡')
          .width(200)
          .backgroundColor('#ED5B8C')
          .stateStyles({
            pressed: {
              .backgroundColor('#EA446C')
            }
          })
          .animation({
            duration: 1000
          })
      }
    }
  }
}

4.3. 遮罩层静态布局

单击“立即抽卡”按钮后显示的遮罩层

  • 标签解构: Column > Text + Image + Button

样式枚举:

  1. 遮罩层整体样式:

宽度 -> 100% 高度 -> 100% 背景色 -> 'rgba(0,0,0,0.8)' 定位 内容主轴对齐方式 -> 居中

  1. 文字: 颜色 -> '#F5EBCF' 大小 -> 25 粗细 -> 600
  2. 图片: 外边距 -> 30 宽度 -> 200
  3. 按钮样式:

宽度 -> 200 高度 -> 50 背景色 -> 透明 边框 -> 粗细 2 颜色 '#FFF9E0'

Column({space: 30}) {
  Text('获取生肖卡')
    .fontColor('#F5EBCF')
    .fontSize(25)
    .fontWeight(600)
  Image($r('app.media.img_00'))
    .width(200)
  Button('开心收下')
    .width(200)
    .height(50)
    .backgroundColor(Color.Transparent)
    .border({width: 2, color: '#FFF9E0'})
}
.width('100%')
  .height('100%')
  .backgroundColor('rgba(0,0,0,0.8)')
  .justifyContent(FlexAlign.Center)
  .position({x: 0, y: 0})

4.4. 遮罩层动态交互

4.4.1. 按钮交互

遮罩层的显示隐藏, 图片添加缩放效果

思路分析:

默认状态

  1. 界面隐藏visibility(Visibility:Hidden)
  2. 生肖卡隐藏(缩放比例为0)

抽卡后状态

  1. 界面显示visibility(Visibility:Visible)
  2. 生肖卡显示(缩放比例为1)

单击“开心收下”按钮

  1. 界面隐藏
 // 是否显示生肖卡界面状态
  @State
  isVisible: boolean = false

  // 生肖卡缩放状态
  @State
  imgX: number = 0
  @State
  imgY: number = 0

// 抽卡按钮
Button('立即抽卡')
  .width(200)
  .backgroundColor('#ED5B8C')
  .stateStyles({
    pressed: {
      .backgroundColor('#EA446C')
    }
  })
  .animation({
    duration: 1000
  })
  .onClick(() => {
    this.isVisible = true
    this.imgX = 1
    this.imgY = 1
  })

// 二. 生肖卡界面
Column({space: 30}) {
  Image($r('app.media.img_00'))
    .width(200)
    .scale({x: this.imgX, y: this.imgY})
    .animation({duration: 400})
  Button('开心收下')
    .onClick(() => {
      // 生肖卡界面隐藏;卡片隐藏
      this.isVisible = false
      this.imgX = 0
      this.imgY = 0
    })
}
  // 使用状态控制整个界面显隐
  .visibility(this.isVisible ? Visibility.Visible : Visibility.Hidden)
4.4.2. 图片数据

随机抽中一张生肖卡,单击“开心收下”按钮,显示对应的生肖卡,角标+1

思路分析:

  1. 随机显示生肖卡
  2. 卡片数量 +1
// 随机生肖卡序号
  @State
  randomIndex: number = -1

Button('立即抽卡')
  .onClick(() => {
    // 随机生肖卡 0-5
    this.randomIndex = Math.floor(Math.random() * 6)
  })
Column({space: 30}) {
  // 使用生成的随机数筛选生肖卡
  Image($r(`app.media.img_0${this.randomIndex}`))
  Button('开心收下')
    .onClick(() => {
      // 收下卡片更新对象数组 -- 替换初始界面图片url和角标数字
      this.images[this.randomIndex] = {
        url: `app.media.img_0${this.randomIndex}`,
        num: this.images[this.randomIndex].num += 1
      }
    })
}

4.5. 中奖结果

6张卡片数量均>=1,则可以抽奖一次(显示抽奖页面:奖品随机)

 4.5.1. 抽奖静态页面

// 抽奖页面-遮罩层
Column({space: 50}) {
  Text('恭喜获得手机一部')
    .fontColor('#F5EBCF')
    .fontSize(25)
    .fontWeight(600)
  Image($r('app.media.hw'))
    .width(300)
  Button('再来一次')
    .width(200)
    .height(50)
    .backgroundColor(Color.Transparent)
    .border({width: 2, color: '#FFF9E0'})
}
.width('100%')
  .height('100%')
  .backgroundColor('rgba(0,0,0,0.8)')
  .justifyContent(FlexAlign.Center)
  .position({x: 0, y: 0})
4.5.2. 条件渲染-抽卡与抽奖页面

集齐6种生肖卡显示抽奖页面,否则显示抽卡页面

// 是否中奖状态
  @State
  isGet: boolean = false

// 三. 抽奖中奖界面
if (this.isGet) {
  Column({space: 50}) {}
}
4.5.3. 抽奖数据处理

判断是否可以抽奖:定义count变量保存已经获得的卡片种类数量(如果每个生肖卡数量>=1,则count+1)

如果count == 6,说明已经得到了6种卡,则可以抽奖,渲染抽中的奖品图片

思路分析:

声明一个变量 保存 中奖的结果 、声明一个变量保存中奖的名称

  1. 声明一个变量保存 获得卡片的种类
  2. 遍历数组, 如果卡片的个数 大于 等于1 获得种类加 1 否则 肯定没有中奖 跳出循环
  3. 判断种类是否有 6 种
    1. 如果等于 6 说明已经集够卡片 中奖结果改为 true
    2. 罗列所有的奖品名称
    3. 获取随机下标 0 -- 2
    4. 获取随机名称
// 奖品状态
  @State
  jiangPin: string = ''

// 抽奖页面-遮罩层
Column({space: 50}) {
  Text('恭喜获得手机一部')
  Image($r(`app.media.${this.prize}`))
  Button('再来一次')
}

Button('开心收下')
  .onClick(() => {
    // 判断是否可以抽奖:定义count变量保存已经获得的卡片种类数量(如果每个生肖卡数量>=1,则count+1)
    // 如果count == 6,说明已经得到了6种卡,则可以抽奖
    // 判断是否中奖
    let count: number = 0
    for (const item of this.images) {
      if (item.num >= 1) {
        count += 1
      } else {
        break
      }
    }
    if (count == 6) {
      this.isGet = true
    }

    // 随机奖品
    const arr: string[] = ['hw', 'xm', 'pg']
    let randomNum: number = Math.floor(Math.random() * 3)
    this.jiangPin = arr[randomNum]
  })

4.6. 再次抽奖

单击“再来一次”按钮,重新抽卡

  1. 关闭遮罩层:中奖状态为 false
  2. 初始化列表数据
Button('再来一次')
  .onClick(() => {
    this.isGet = false
    this.images = [
      {url: 'app.media.bg_00', num: 0},
      {url: 'app.media.bg_01', num: 0},
      {url: 'app.media.bg_02', num: 0},
      {url: 'app.media.bg_03', num: 0},
      {url: 'app.media.bg_04', num: 0},
      {url: 'app.media.bg_05', num: 0}
    ]
  })

案例代码:【免费】HarmonyOs应用基础-ArkTS-核心-基础-抽奖案例代码资源-CSDN文库


http://www.kler.cn/a/299552.html

相关文章:

  • 实验八 JSP访问数据库
  • 基于Django的Boss直聘IT岗位可视化分析系统的设计与实现
  • Google 和 Meta 携手 FHE 应对隐私挑战
  • AI时序预测: iTransformer算法代码深度解析
  • jEasyUI 转换 HTML 表格为数据网格
  • Baklib揭示内容中台与人工智能技术的创新协同效应
  • 深入掌握大模型精髓:《实战AI大模型》带你全面理解大模型开发!
  • JVM、JRE和 JDK:理解Java开发的三大核心组件
  • 内衣专用洗衣机怎么样?五款高分热门产品汇总,亮点满满
  • 计算机毕业设计 校内跑腿业务系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试
  • SprinBoot+Vue个性化旅游推荐系统的设计与实现
  • 多个时间序列的滞后相关性
  • 生物信息名词汇总|生物信息基础知识
  • 医疗图像配准方法
  • 独立产品灵感周刊 DecoHack #067 - 摸鱼神器与AI视频创作工具
  • C# 多线程操作同一个文件,如何避免冲突
  • FFCD:森林火灾分类数据集(猫脸码客 第184期)
  • 解决python报错:AttributeError: module ‘matplotlib.cm‘ has no attribute ‘spectral‘
  • 基于YOLOv8的风力涡轮机表面损坏检测系统
  • Linux和C语言(Day10)
  • NVDLA专题14:Runtime environment-用户模式驱动
  • 美客多自养号怎么测?看看这个专业指南和深度分析吧!
  • 【题目】数据分析与数据思维选择题
  • 【Kubernetes】常见面试题汇总(七)
  • Android解析JSON格式数据
  • Uniapp + Vite + Vue3 + uView + Pinia 实现自定义底部 Tabbar(最新保姆级教程)