利用鸿蒙@Prop的特性,我画了一条游动的蛇?

110 阅读1分钟

直接上图:

image.png

理解@Prop

  1. 初始渲染:

    1. 执行父组件的build()函数将创建子组件的新实例,将数据源传递给子组件;
    2. 初始化子组件@Prop装饰的变量。

    ps:根据渲染规则,可以看到例子中的Component是逐个刷新的,时间差导致了动画的效果。对比compose则不是这样。

  2. 更新:

    1. 子组件@Prop更新时,更新仅停留在当前子组件,不会同步回父组件;
    2. 当父组件的数据源更新时,子组件的@Prop装饰的变量将被来自父组件的数据源重置,所有@Prop装饰的本地的修改将被父组件的更新覆盖。

说明: 1.在组件复用场景,建议@Prop深度嵌套数据不要超过5层,嵌套太多会导致深拷贝占用的空间过大以及GarbageCollection(垃圾回收),引起性能问题,此时更建议使用@ObjectLink 2.@Prop装饰的数据更新依赖其所属自定义组件的重新渲染,所以在应用进入后台后,@Prop无法刷新,推荐使用@Link代替。

上代码

const Body = "oOo"
const Gap = " "
const MAX = 10
const GapStep = 2

@Component
struct FunnyProp {
  @Prop dateTime: string = ""
  @Prop index: number = 0
  maxIndex: number = 1000

  gaps(gap = Gap, count: number): string {
    let result = gap
    while (count > 0) {
      result += gap
      count--
    }
    return result
  }

  createByIndex(max = MAX, gap = Gap, gapStep = GapStep): string {
    let tmp = this.index % max
    let result = ""
    if (tmp <= max / 2) {
      while (max - tmp > 0) {
        result += this.gaps(gap, gapStep)
        tmp++
      }
    } else {
      while (tmp > 0) {
        result += this.gaps(gap, gapStep)
        tmp--
      }
    }
    return result + Body
  }

  build() {
    Column() {
      Text(`${this.createByIndex()}`).fontColor(Color.Red)
      if (this.index < this.maxIndex) {
        FunnyProp({ dateTime: this.dateTime, index: this.index + 1 })
      }
    }
  }
}

@Component
export struct FunnyPropTest {
  @State index: number = 0
  @State taskId ?: number | null = null
  internal: number = 100

  aboutToAppear(): void {
    this.start()
  }

  aboutToDisappear(): void {
    this.stop()
  }

  doing(): boolean {
    console.info(`FunnyPropTest::doing taskId: ${this.taskId}`)
    return (this.taskId != undefined && this.taskId != null)
  }

  status() {
    if (this.doing()) {
      return "停止"
    } else return "开始"
  }

  stop() {
    console.info(`FunnyPropTest::stop taskId: ${this.taskId}`)
    clearInterval(this.taskId)
    this.taskId = null
  }

  start() {
    console.info(`FunnyPropTest::start taskId: ${this.taskId}`)
    this.taskId = setInterval(() => {
      this.index++
    }, this.internal)
  }

  toggle() {
    console.info(`FunnyPropTest::toggle taskId: ${this.taskId}`)
    if (this.doing()) {
      this.stop()
    } else {
      this.start()
    }
  }

  build() {
    Column() {
      Button(`${this.status()}`).onClick(() => {
        this.toggle()
      })
      FunnyProp({ index: this.index })
    }
  }
}

见笑了各位!