一大波女生、男生适用的最新鸿蒙练手案例来袭

简介: 一大波女生、男生适用的最新鸿蒙练手案例来袭

一大波女生、男生适用的最新鸿蒙练手案例来袭

介绍

以下案例适合刚开始手鸿蒙开发的小伙伴,有大量的最新逻辑锻炼、鸿蒙核心语法、使用最新鸿蒙的@Local、@Computed 等装饰器来完成。

另外,考虑在学习知识的知识时候,优先关注核心功能,所以提供的布局都会适当简化,但是能保证把核心功能展示出来。

每一个案例会点出终点和核心知识,让学习者可以练习完毕,可以得到什么。

学习的路线

  1. 先看效果
  2. 复现效果
  3. 如果有对代码产生的疑问,可以在评论区内直接提出,有疑问,必回复
  4. 如果能帮助到你,就很好了。😄

点击高亮

  1. 练习基本的线性布局
  2. 练习基本的数组使用
  3. 练习列表渲染语法 ForEach
  4. 练习布局中的状态切换 三元表达式
  5. 掌握通用的点击高亮

@Entry
@ComponentV2
struct Index {
  @Local
  list: string[] = ["小明", "小红", "小黑", "小黄"]
  // 声明一个数字 表示你当前选中的按钮的下标
  @Local
  select: number = 1
  build() {
    Column() {
      ForEach(this.list, (item: string, index: number) => {
        Button(item + "  " + (this.select == index))
          .backgroundColor(this.select == index ? "#ffcd43" : "#007dfe")
          .onClick(() => {
            this.select = index
          })
      })
    }
    .width("100%")
    .height("100%")
    .padding({ top: 100 })
  }
}

待办列表

  1. 新手上手新的编程语言的必做案例 crud - 增删该查
  2. 练习 V2装饰器、@Local、@Computed、事件等
  3. 打通 状态 -> UI 、 UI-> 状态 的一些交互

@ObservedV2
class Task {
  @Trace task: string = ""
  @Trace isFinished: boolean = false
}
@Entry
@ComponentV2
struct Index {
  // 任务列表
  @Local
  list: Task[] = [
  // { task: "数组学习", isFinished: true },
  // { task: "函数学习", isFinished: false }
  ]
  // 输入框输入的内容
  @Local
  inpValue: string = ""
  // 未完成数量
  @Computed
  get statistics() {
    let undoneNum = this.list.filter(v =>!v.isFinished).length
    let doneNum = this.list.length - undoneNum
    return [undoneNum, doneNum]
  }
  // 清理已经完成的任务
  onClear = () => {
    //   筛选 留下未完成
    this.list = this.list.filter((v =>!v.isFinished))
  }
  // 删除
  onDelete = (index: number) => {
    this.list.splice(index, 1)
  }
  build() {
    Column() {
      Row() {
        Button("清理已完成")
          .onClick(this.onClear)
      }
      Row() {
        Text(`未完成的数量 ${this.statistics[0]}`)
        Text(`完成的数量 ${this.statistics[1]}`)
      }
      .width("80%")
      .justifyContent(FlexAlign.SpaceAround)
      Row() {
        TextInput()
          .width(200)
          .onChange(value => {
            this.inpValue = value
          })
        Button("确认")
          .onClick(() => {
            // 熟练 探囊取物!!
            // 先判断当前任务有没有出现过
            const isExit = this.list.some(element => element.task == this.inpValue)
            if (!isExit) {
              const p = new Task()
              p.task = this.inpValue
              this.list.push(p)
            }
          })
      }
      ForEach(this.list, (item: Task, index: number) => {
        Row() {
          Text(item.task)
            .fontColor(item.isFinished ? "#666" : "#000")
            .decoration({
              type: item.isFinished ? TextDecorationType.LineThrough : TextDecorationType.None
            })
            .fontStyle(item.isFinished ? FontStyle.Italic : FontStyle.Normal)
            .onClick(() => {
              this.onDelete(index)
            })
          Button(item.isFinished ? "继续" : "完成")
            .backgroundColor(item.isFinished ? "#ffa601" : "#007dfe")
            .onClick(() => {
              this.list[index].isFinished = !this.list[index].isFinished
            })
        }
      })
    }
    .width("100%")
    .height("100%")
    .padding({ top: 100 })
  }
}


B站显示更多

  1. 练习Flex布局的换行
  2. 练习Scroll布局的水平滚动
  3. 练习绝对定位-水平居中
  4. 练习条件渲染

@Entry
@ComponentV2
struct Index {
  @Local
  list: string[] =
    ["首页", "动画", "番剧", "国创", "音乐", "舞蹈", "游戏", "知识", "科技", "运动", "汽车", "生活", "美食", "动物圈",
      "鬼畜", "时尚", "娱乐", "影视", "纪录片", "电影", "电视剧", "直播", "课堂"]
  // 是否显示更多
  @Local
  isShowMore: boolean = false
  build() {
    Column() {
      Row({ space: 5 }) {
        Scroll() {
          // true 换行
          Flex({ wrap: this.isShowMore ? FlexWrap.Wrap : FlexWrap.NoWrap }) {
            ForEach(this.list, (item: string) => {
              Text(item)
                .margin(10)
            })
          }
        }
        .scrollable(ScrollDirection.Horizontal)
        .layoutWeight(1)
        // .backgroundColor(Color.Yellow)
        .padding({
          bottom: this.isShowMore ? 30 : 0
        })
        if (this.isShowMore) {
          Image($r("app.media.app_icon"))
            .width(20)
            .position({
              left: "50%",
              bottom: 0
            })
            .translate({
              x: -10
            })
            .onClick(() => {
              this.isShowMore = !this.isShowMore
            })
        } else {
          Image($r("app.media.app_icon"))
            .width(20)
            .onClick(() => {
              this.isShowMore = !this.isShowMore
            })
        }
      }
      .width("100%")
      .backgroundColor(Color.Red)
    }
    .width("100%")
    .height("100%")
  }
}

仿考研日程

  1. 练习如何根据需求来拆分数据
  2. 简单的渲染

// 二级目录
interface SubContent {
  subTitle: string
  subContent: string
}
// 一级目录
interface OneContent {
  title: string
  content: SubContent[]
}
@Entry
@ComponentV2
struct Index {
  @Local
  list: OneContent[] = [
    {
      title: "统考",
      content: [
        {
          subTitle: "国家线",
          subContent: "2024。。。。"
        }, {
        subTitle: "考研复试流程图",
        subContent: ""
      }
      ]
    },
    {
      title: "统考22",
      content: [
        {
          subTitle: "国家线22",
          subContent: "2024。。。。22"
        }, {
        subTitle: "考研复试流程图22",
        subContent: ""
      }
      ]
    }
  ]
  // 选中标题的下标
  @Local
  current: number = 0
  build() {
    Column() {
      // 1 标题
      Row({ space: 10 }) {
        ForEach(this.list, (item: OneContent, index: number) => {
          Text(item.title)
            .fontColor(this.current == index ? "#0094ff" : "#000")
            .onClick(() => {
              this.current = index
            })
        })
      }
      //   2 内容
      Column() {
        ForEach(this.list[this.current].content, (item: SubContent) => {
          Column() {
            Text(item.subTitle)
            Text(item.subContent)
          }
        })
      }
    }
    .width("100%")
    .height("100%")
    .backgroundColor("#eee")
  }
}

仿vantUI -倒计时

  1. 练习定时器
  2. 练习一点关于时间处理的逻辑功能

@Entry
@ComponentV2
struct Index {
  @Local
  str: string = ""
  // 时间 毫秒
  time: number = 5 * 60 * 60 * 1000
  tid: number = -1
  build() {
    Column() {
      Button("开始倒计时")
        .onClick(() => {
          // setInterval 时间间隔最少 是10ms
          this.tid = setInterval(() => {
            this.time -= 10
            //   计算小时 整数 parseInt  Math.floor()
            // parseInt 只能传递字符串类型
            const hour = Math.floor(this.time / 1000 / 60 / 60)
            const minute = Math.floor(this.time / 1000 / 60 % 60)
            const seconde = Math.floor(this.time / 1000 % 60)
            const milliSeconde = this.time % 1000
            this.str = `${hour}:${minute}:${seconde}.${milliSeconde}`
          }, 10)
        })
      Button("暂停")
        .onClick(() => {
          clearInterval(this.tid)
        })
      Text(this.str)
        .fontSize(30)
    }
  }
}

仿掘金抽奖

  1. 练习flex布局-换行
  2. 练习随机数
  3. 练习数组+随机数实现随机获取元素

@Entry
@ComponentV2
struct Index {
  @Local
  list: string[] = [
    "4090",
    "4399",
    "大彩电",
    "iphone16",
    "meta70",
    "Mac",
    "小牛电动车",
    "迪拜7日游",
    "北京房子一套"
  ]
  @Local
  current: number = 0
  // 根据下标设置奖品高亮
  setHighline(index: number) {
    this.current = index
  }
  build() {
    Column() {
      Flex({
        wrap: FlexWrap.Wrap
      }) {
        ForEach(this.list, (item: string, index: number) => {
          Text(item)
            .width("33.33%")
            .padding({
              top: 20, bottom: 20
            })
            .border({
              width: 1
            })
            .backgroundColor(this.current == index ? "#e37815" : "#fff")
        })
      }
      Button("开始抽啦")
        .onClick(() => {
          //  开始抽奖
          let tid = setInterval(() => {
            // 等于 数组长度范围内的随机数
            const index = Math.floor(Math.random() * this.list.length)
            this.setHighline(index)
          }, 10)
          //   开启5s种延时器  -  停止定时器
          setTimeout(() => {
            clearInterval(tid)
          }, 5000)
        })
    }
  }
}

仿掘金抽奖 - 不重复抽奖

  1. 加强逻辑处理,如何实现不重复抽奖
  2. 练习一些数组的方法
  3. 练习使用 @Computed

@Entry
@ComponentV2
struct Index {
  @Local
  list: string[] = [
    "4090",
    "4399",
    "大彩电",
    "iphone16",
    "meta70",
    "Mac",
    "小牛电动车",
    "迪拜7日游",
    "北京房子一套"
  ]
  @Local
  selectedList: number[] = []
  @Local
  current: number = 0
  // 奖池
  @Computed
  get newList() {
    const newList: number[] = []
    for (let index = 0; index < this.list.length; index++) {
      let item = this.selectedList.find(v => v === index)
      if (!item) {
        newList.push(index)
      }
    }
    return newList
  }
  // 根据下标设置奖品高亮
  setHighline(index: number) {
    this.current = index
  }
  build() {
    Column() {
      Flex({
        wrap: FlexWrap.Wrap
      }) {
        ForEach(this.list, (item: string, index: number) => {
          Text(item)
            .width("33.33%")
            .padding({
              top: 20, bottom: 20
            })
            .border({
              width: 1
            })
            .backgroundColor(
              this.selectedList.includes(index) ? "#e37815" :
                (this.current == index ? "#e37815" : "#fff"))
        })
      }
      Button("开始抽啦")
        .onClick(() => {
          //  开始抽奖
          let tid = setInterval(() => {
            // 等于 数组长度范围内的随机数
            const index = Math.floor(Math.random() * this.newList.length)
            this.setHighline(this.newList[index])
          }, 10)
          //   开启5s种延时器  -  停止定时器
          setTimeout(() => {
            clearInterval(tid)
            this.selectedList.push(this.current)
          }, 1000)
        })
    }
  }
}

仿vantUI-分页组件-简单版本

  1. 练习基本的鸿蒙线性布局
  2. 练习条件渲染
  3. 练习逻辑能力

@Entry
@ComponentV2
struct Index {
  @Local
  list: string[] = ['1', '2', '3', '4', '5']
  @Local
  current: number = 4
  build() {
    Column() {
      Row({ space: 2 }) {
        Button("上一页")
          .enabled(this.current != 0)
          .backgroundColor("#fff")
          .fontColor("#0094ff")
          .stateStyles({
            disabled: {
              .backgroundColor("#eee")
            }
          })
          .onClick(() => {
            this.current--
          })
        ForEach(this.list, (item: string, index: number) => {
          Button(item)
            .backgroundColor(this.current == index ? "#0094ff" : "#fff")
            .fontColor(this.current == index ? "#fff" : "#0094ff")
            .onClick(() => {
              this.current = index
            })
        })
        Button("下一页")
          .enabled(this.current != this.list.length - 1)
          .backgroundColor("#fff")
          .stateStyles({
            disabled: {
              .backgroundColor("#eee")
            }
          })
          .fontColor("#0094ff")
          .onClick(() => {
            this.current++
          })
      }
    }
    .width("100%")
    .height("100%")
    .padding({
      top: 100
    })
    .backgroundColor("#eee")
  }
}

仿vantUI-分页组件-复杂版本

  1. 练习基本的鸿蒙线性布局
  2. 练习条件渲染
  3. 练习复杂的逻辑能力

@Entry
@ComponentV2
struct Index {
  @Local list: number[] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
  @Local
  test: number = 1
  @Local 
  showList: number[] = [1, 2, 3]
  change() {
    if (this.test > 1 && this.test < this.list.length) {
      this.showList = [this.test - 1, this.test, this.test + 1]
    }
  }
  previous() {
    this.test--
    this.change()
  }
  next() {
    this.test++
    this.change()
  }
  build() {
    Column() {
      Row() {
        Button("上")
          .enabled(this.test != 1)
          .backgroundColor("#ccc")
          .onClick(() => {
            this.previous()
          })
        if (this.test > 2) {
          Button("...")
            .backgroundColor("#ccc")
            .onClick(() => {
              this.previous()
            })
        }
        ForEach(this.showList, (item: number) => {
          Button(item.toString())
            .backgroundColor(this.test == item ? Color.Blue : "#ccc")
            .onClick(() => {
              this.test = item
              this.change()
            })
        })
        if (this.test < this.list[this.list.length-1] - 1) {
          Button("...")
            .backgroundColor("#ccc")
            .onClick(() => {
              this.next()
            })
        }
        Button("下")
          .enabled(this.test != this.list[this.list.length-1])
          .backgroundColor("#ccc")
          .onClick(() => {
            this.next()
          })
      }
    }
  }
}

小结

如果部分内容中的图片不存在,自己随机替换即可。

目录
相关文章
|
29天前
|
JSON JavaScript 前端开发
harmony-chatroom 自研纯血鸿蒙OS Next 5.0聊天APP实战案例
HarmonyOS-Chat是一个基于纯血鸿蒙OS Next5.0 API12实战开发的聊天应用程序。这个项目使用了ArkUI和ArkTS技术栈,实现了类似微信的消息UI布局、输入框光标处插入文字、emoji表情图片/GIF动图、图片预览、红包、语音/位置UI、长按语音面板等功能。
62 2
|
4月前
|
开发框架 前端开发 开发工具
一个小案例带你快速了解鸿蒙ArkUI的基本使用
一个小案例带你快速了解鸿蒙ArkUI的基本使用
125 4
|
XML JSON 开发框架
两个案例五分钟轻松入门Harmony(鸿蒙)开发
两个案例五分钟轻松入门Harmony(鸿蒙)开发
424 0
两个案例五分钟轻松入门Harmony(鸿蒙)开发
|
24天前
|
JavaScript 安全 前端开发
【HarmonyOS开发】ArkTS基础语法及使用(鸿蒙开发基础教程)
【HarmonyOS开发】ArkTS基础语法及使用(鸿蒙开发基础教程)
279 4
|
23天前
|
存储 数据安全/隐私保护
鸿蒙开发:自定义一个动态输入框
在鸿蒙开发中,如何实现这一效果呢,最重要的解决两个问题,第一个问题是,如何在上一个输入框输入完之后,焦点切换至下一个输入框中,第二个问题是,如何禁止已经输入的输入框的焦点,两个问题解决完之后,其他的就很是简单了。
48 13
鸿蒙开发:自定义一个动态输入框
|
26天前
|
小程序 测试技术 API
鸿蒙原生开发手记:03-元服务开发全流程(开发元服务,只需要看这一篇文章)
本文详细介绍元服务的开发及上架全流程,涵盖元服务的特点、创建项目、服务卡片、签名打包、开发测试及上架审核等环节,帮助开发者轻松掌握从零开始开发并发布元服务的全过程。元服务以其轻量、免安装、易于使用等特点,成为未来服务提供的重要形式。
70 13
鸿蒙原生开发手记:03-元服务开发全流程(开发元服务,只需要看这一篇文章)
|
23小时前
|
索引
鸿蒙开发:ForEach中为什么键值生成函数很重要
在列表组件使用的时候,如List、Grid、WaterFlow等,循环渲染时都会使用到ForEach或者LazyForEach,当然了,也有单独使用的场景,如下,一个很简单的列表组件使用,这种使用方式,在官方的很多案例中也多次出现,相信在实际的开发中多多少少也会存在。
鸿蒙开发:ForEach中为什么键值生成函数很重要
|
1月前
|
Android开发
鸿蒙开发:自定义一个简单的标题栏
本身就是一个很简单的标题栏组件,没有什么过多的技术含量,有一点需要注意,当使用沉浸式的时候,注意标题栏的位置,需要避让状态栏。
鸿蒙开发:自定义一个简单的标题栏
|
1月前
|
API
鸿蒙开发:切换至基于rcp的网络请求
本文的内容主要是把之前基于http封装的库,修改为当前的Remote Communication Kit(远场通信服务),无非就是通信的方式变了,其他都大差不差。
鸿蒙开发:切换至基于rcp的网络请求
|
29天前
|
传感器 数据处理 数据库
鸿蒙开发Hvigor插件动态生成代码
【11月更文挑战第13天】Hvigor 是鸿蒙开发中的构建系统插件,主要负责项目的构建、打包及依赖管理,并能根据预定义规则动态生成代码,如数据库访问、网络请求等,提高开发效率和代码一致性。适用于大型项目初始化和组件化开发。