鸿蒙应用开发-时间都去哪了?

368 阅读4分钟

鸿蒙应用开发-时间都去哪了

在编程中,时间的概念主要涉及对时间进行度量、操作和管理。编程语言通常提供了丰富的时间处理功能,帮助开发者实现从简单的时间戳获取到复杂的定时任务调度。那么,作为开发者的我们怎么能不会使用计时器?如果你真不会,那就跟我一起学吧。💕💕💕

计时器

计时器是一种用于测量时间间隔的工具,通常用于控制事件的发生时间或持续时间。在鸿蒙OS中,计时器有多种实现方式和用途,以下是常见的计时器类型:定时器\textcolor{Red}{定时器}延时器\textcolor{Red}{延时器}

定时器setInterval

setInterval是在一定时间间隔来重复执行指定的函数,所有的定时器、延时器在创建都有一个属于自己的id,当我们对其的关闭需要用到id

const timeId=setInterval(()=>{
    //执行的逻辑
},时间)

clearInterval(timeId)//根据id清除定时器

在很多登录页面都会用到短信验证码登录,让我们一起看看下面这个案例吧!!!

案例:

recording

基本框架:

@Entry
@Component
struct LoginDemo {
  build() {
    Column() {
      this.titleBuilder()
      TextInput({ placeholder: '请输入手机号' })
        .textInputExtend()
      Divider()
      Row() {
        TextInput({ placeholder: '请输入验证码' })
          .textInputExtend()
          .layoutWeight(1)
        Text('发送验证码')
          .fontSize(14)
          .fontColor(Color.Gray)
      }
      .width('100%')

      Divider()

      Button('登录')
        .width('100%')
        .type(ButtonType.Normal)
        .backgroundColor('#ea6051')
        .margin({ top: 50 })

    }
    .padding({ top: 80, left: 40, right: 40 })
    .width('100%')
    .alignItems(HorizontalAlign.Start)
  }

  @Builder
  titleBuilder() {
    Text('短信登录')
      .fontSize(25)
      .fontWeight(600)
      .margin({ bottom: 30 })
  }
}

@Extend(TextInput)
function textInputExtend() {
  .backgroundColor(Color.White)
  .padding({ left: 0, top: 20, bottom: 20 })
  .placeholderColor('#ccc')
}

问题分析

这边我们实现的功能无非就是当用户点击了这个按钮以后,然后开始倒计时(中间跳过服务器和后端处理),当倒计时为0的时候呢,用户可以重新点击按钮。

  1. 先定义两个状态变量sendCode,num

    image-20240821200737110

  2. 编写点击事件,里面是两次条件渲染

  3. num为60时,时间数字开始递减(这里时防止多次点击的影响),sendCode变化为num秒重新发送

image-20240821200909855

  1. 第一次判断后,开启定时器(里面逻辑:时间数字递减,文本变化)

    image-20240821201142139

  2. 第二次判断,当num为0时,num重置为60,关闭定时器,文本重制

    image-20240821201240851

@Entry
@Component
struct Index {
  @State
  sendCode:string='发送验证码'  //按钮上显示的文字会随时间数字的变化而变化
  @State
  num:number=60 //时间数字
  build() {
    Column() {
        Button(this.sendCode)
          .backgroundColor(Color.Pink)
          .fontSize(14)
          .fontColor(Color.Gray)
          .onClick(()=>{
            if (this.num==60) {
              this.num--
              this.sendCode=`${this.num}秒重新发送`
              const tid=setInterval(()=>{
                this.num--
                this.sendCode=`${this.num}秒重新发送`
                if (this.num==0) {
                  this.num=60
                  clearInterval(tid)
                  this.sendCode='发送验证码'
                }
              },100)
            }
          })
    }
    .padding({ top: 80, left: 40, right: 40 })
    .width('100%')
    .alignItems(HorizontalAlign.Start)
  }
}

延时器setTimeout

setTimeout当设置的时间到了之后就会去执行指定的逻辑操作,跟setInterval一样都拥有一个id,但是这边需要注意的是:如果同时使用定时器和延时器的话,他们的id是层叠存在的。(所以,再关闭的时候要非常小心!!!)

image-20240821202359381

案例:

这边由于过于简单就不讲了,要讲的是代码优化。下图可以看到我们每敲一个字母都会将内容传递给后端,每发一次就是一次网络请求,如果说每次都发的话,那么我们的服务器压力就会特别大,所以这边我教大家控制减少发送,俗称防抖

recording

防抖Debounce

介绍

防抖(Debounce):防抖技术是通过延迟函数来控制时间在短时间内连续触发的执行次数,有了一定的时间间隔后,事件最后一次触发后的操作才会执行。拿上面的案例举例子,xiaomi我需要敲六次键盘,在每次敲击键盘后面我加个延时器,设定一个2s的时间,若这2s内我没有输入,则将此时的数据传送给后端。

具体实现

image-20240821204809560

代码:

@Entry
@Component
struct Index {
  tid:number=-1 //id
  build() {
    Column(){
      TextInput()
        .onChange((value)=>{
          clearTimeout(this.tid)  //关闭延时器
          this.tid=setTimeout(()=>{
            console.log('发送给后端',value) //发送数据,在实际开发中这里应该是逻辑                                             操作的函数
          },1000)
        })
    }
  }
}

节流Throttle

介绍

节流是一种技术,通过控制在一定的时间间隔内只执行第一次函数,来限制事件的触发次数,与防抖是相反的,一般成对出现。用途:处理滚动事件,限制频繁触发的情况,例如在滚动加载场景中,只有在用户停止滚动一段时间后才加载内容。

具体实现

场景:

image-20240821205504376

这边一组是30个数字,有上下滚动的功能,当滚动底部时,需要生成一组新的30个数字。这边难点在于,每当触底的时候可能重复生成数字。(这边tid=-1时也就代表第一次哈)

image-20240821210307181

完整代码:

@Entry
@Component
struct Index {
  @State
  list: number[] = Array.from({ length: 30 }, (val: undefined, index: number) => index)
  addList = () => {

    const newList: number[] = Array.from({ length: 30 }, (val: undefined, index: number) => index)
    this.list.push(...newList)
  }
  // tid: number = -1
  // index: number = 0


  isRun: boolean = false

  build() {
    List() {
      ForEach(this.list, (item: undefined, index: number) => {
        ListItem() {
          Text(index + "")
            .width("100%")
            .padding(20)
        }
        .width("100%")

      })

    }
    .divider({ strokeWidth: 1, color: "#f00" })
    .listDirection(Axis.Vertical)
    //   绑定事件
    .onReachEnd(() => {
      // 判断有没有逻辑正在进行
      if (this.isRun) {
        return
      }
      this.isRun = true

      setTimeout(() => {
        this.addList()
        //  业务做完了
        this.isRun = false
      }, 3000)

    })
  }
}