鸿蒙学习——数据传递

284 阅读4分钟

数据传递

数组

简单类型数组

基础代码:

@Entry
@Component
struct Index {
  @State
  numArr: number[] = [100, 200, 300]
  build() {
    Column({ space: 10 }) {
      ForEach(this.numArr, (item: number, index: number) => {
        Button(item.toString())
        .onClick(()=>{
        })
      })
    }
    .width("100%")
    .height("100%")
    .justifyContent(FlexAlign.Center)
  }
}

错误写法:鸿蒙内部对于item可能常量形式声明,常量不能被修改 0.png 正确写法: image.png

引用类型数组

基础代码:

import { promptAction } from '@kit.ArkUI'
interface IStar {
  name: string
  hot: number
}
@Entry
@Component
struct Index {
  @State
  starList: IStar[] = [{name: "周杰伦",hot: 100},{name: "费玉清",hot: 50},{name: "周华健",hot: 200},]
  build() {
    Column({ space: 10 }) {
      ForEach(this.starList, (item: IStar, index: number) => {
        Button(`${item.name} - ${item.hot}`)
          .onClick(() => {
          })
      })
    }
    .width("100%")
    .height("100%")
    .justifyContent(FlexAlign.Center)
  }
}

错误写法:如若数据是引用数据类型,常量 内存地址不能修改 image.png
错误写法:值改变,但UI不更新 image.png 正确写法: image.png

单向->@Prop

@Prop可以实现父组件->子组件的单向数据传递,父组件数据改变,子组件数据随之改变;但子组件直接改变数据,父组件不会随之发生改变

简单类型数组-组件

基础代码:

@Component
struct MyButton {
  @Prop
  item: number
  build() {
    Column() {
      Button(this.item.toString())
        .onClick(() => {
        })
    }
  }
}
@Entry
@Component
struct Index {
  @State
  numArr: number[] = [100, 200, 300]
  build() {
    Column({ space: 10 }) {
      ForEach(this.numArr, (item: number, index: number) => {
        MyButton({item})
      })
    }
    .width("100%")
    .height("100%")
    .justifyContent(FlexAlign.Center)
  }
}

错误写法:子组件设置点击事件,子组件的值改变,而父组件的值不随之改变
image.png
正确写法: image.png

引用类型数组-组件

基础代码

interface IStar {
  name: string
  hot: number
}
@Component
struct MyButton {
  @Prop
  item: IStar
  build() {
    Column() {
      Button(`${this.item.name} - ${this.item.hot}`)
        .onClick(() => {
        })
    }
  }
}
@Entry
@Component
struct Index {
  @State
  starList: IStar[] = [{name: "周杰伦",hot: 100},{name: "费玉清",hot: 50},{name: "周华健",hot: 200},]
  build() {
    Column({ space: 10 }) {
      ForEach(this.starList, (item: IStar, index: number) => {
        MyButton({ item: item })
      })
    }
    .width("100%")
    .height("100%")
    .justifyContent(FlexAlign.Center)
  }
}

错误写法:子组件中设置点击事件,点击使子组件中的hot数据直接自增,但可以观察到父组件中的hot数据并没有随之自增 image.png
正确写法:点击事件,点击使子组件中数据自增,父组件中的数据也随之自增 image.png

双向->@Link

单一的@Prop只能实现父组件->子组件的单向数据传递
配合:

const item = this.数组[index]          
item.数组中某个元素属性++       
this.数组.splice(index,1,item)       

虽然可以实现双向数据传递,但避免不了一些弊端,如:上述过程会使得整个数组所有数据刷新,在这里体现的不是很明显,但如果是有图片的数据,会发现,每次点击的发生改变的时候,图片也会随之刷新
@Link可以实现父组件<->子组件的双向数据传递,父组件数据修改的同时,子组件数据也随之修改;子组件数据直接修改时,父组件数据也随之修改。避免上述过程中出现的整个刷新的问题

@Link修饰简单类型数据

image.png

@Component
struct son {
  // @Prop //父->子单向 可以不赋初值
  @Link // 父<=>子双向
  snum:number
  build() {
    Button(`子组件 ${this.snum}`)
      .onClick(()=>{
        this.snum++
      })
  }
}
@Entry
@Component
struct Index {
  @State
  fnum:number = 100
  build() {
    Column({space:10}){
      Button(`父组件 ${this.fnum}`)
        .onClick(()=>{
          this.fnum++
        })
      son({snum:this.fnum})
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

@Link修饰引用类型数据

image.png

interface IPerson{
  age:number
}
@Component
struct son {
  // @Prop //父->子单向 可以不赋初值
  @Link // 父<=>子双向
  sperson:IPerson
  build() {
    Button(`子组件 ${this.sperson.age}`)
      .onClick(()=>{
        this.sperson.age++
      })
  }
}
@Entry
@Component
struct Index {
  @State
  fperson:IPerson = {
    age:100
  }
  build() {
    Column({space:10}){
      Button(`父组件 ${this.fperson.age}`)
        .onClick(()=>{
          this.fperson.age++
        })
      son({sperson:this.fperson})
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

@Link修饰深层次引用类型

@Link无法修饰深层次引用类型,过程中会导致子组件无法显示 image.png

import { promptAction } from '@kit.ArkUI'
interface IDog{
  weight:number
}
interface IPerson{
  dog:IDog
}
@Component
struct son {
  // @Prop //父->子单向 可以不赋初值
  @Link // 父<=>子双向
  dog:IDog
  build() {
    Button(`子组件 ${this.dog.weight}`)
      .onClick(()=>{})
  }
}
@Entry
@Component
struct Index {
  @State
  fperson:IPerson = {
    dog:{
      weight:200
    }
  }
  build() {
    Column({space:10}){
      Button(`父组件 ${this.fperson.dog.weight}`)
        .onClick(()=>{
          //鸿蒙没有对深层次的数据 做监听------
          //UI不会更新
          //数据是否发生变化?数据没有变化
          //this.fperson.dog.weight++//无效
          // 数组.splice
          // this.list[index] = .....
          // this.list.age++
          const weight = this.fperson.dog.weight + 1
          this.fperson.dog = { weight: weight }
          promptAction.showToast({message:`${this.fperson.dog.weight}`})
        })
      son({dog:this.fperson.dog})//无效,子组件无法显示
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }
}

@Link无法修饰被ForEach循环出来的item

使用@Link修饰被ForEach循环出来的item->子组件({item})报错,程序无法运行
则@Link无法修饰被ForEach循环出来的item image.png

@Component
struct MyButton {
  @Link
  item: number
  build() {
    Column() {
      Button(this.item.toString())
    }
  }
}
@Entry
@Component
struct Index {
  @State
  numArr: number[] = [100, 200, 300]
  build() {
    Column({ space: 10 }) {
      ForEach(this.numArr, (item: number) => {
        // 提示出错
        MyButton({ item })
      })
    }
    .width("100%")
    .height("100%")
    .justifyContent(FlexAlign.Center)
  }
}