组件状态共享

2024-01-24  本文已影响0人  家乡的蝈蝈

1、组件状态共享

  State是当前组件的状态, 用State修饰的数据变化会驱动UI的更新(只有第一层)
  父传子的时候,子组件定义变量的时候,如果没有任何的修饰符,那么该值只会在第一次渲染时生效

1.1、状态共享-父子单向

  @Prop 装饰的变量可以和父组件建立单向的同步关系。@Prop 装饰的变量是可变的,但是变化不会同步回其父组件。-Prop是用在子组件中的
  Prop只能修饰string number boolean类型的数据- (Next全部都支持了各种类型)

@Entry
@Component
struct PropCase {
  @State message: string = 'Hello World'
  @State num:number = 0
  build() {
    Row() {
      Column({space:20}) {
        Text(this.num.toString()).fontSize(50).fontWeight(FontWeight.Bold)
          .onClick(() => {
            this.num++
          })
        Divider()
          .strokeWidth(6)
        Child({num:this.num})

      }
      .width('100%')
    }
    .height('100%')
  }
}

@Component
struct Child {
  @Prop
  num:number
  build() {
    Text(this.num.toString()).fontSize(40).fontColor(Color.Red)
      .onClick(() => {
        this.num++
      })
  }
}

  我们发现使用Prop修饰的状态,只会在当前子组件生效,不会传导到父组件,所以它属于一种单向传递

1.2、状态共享-父子双向

Child({num:$num})
@Link num:number
// 子组件中被@Link装饰的变量与其父组件中对应的数据源建立双向数据绑定

  需要注意的是,Link修饰的变量类型变得更为宽泛,支持string、number、boolean、enum Object Class以及这些类型对应的数组
小结:
调试技巧:

ArkTS所有的响应式更新都只能监听到我们的第一层数据
Link修饰的数据必须得是最外层的 State数据

@Entry
@Component
struct LinkCase {
  @State message: string = 'Hello World'
  @State
  list:FoodClass[] =  [{
    order_id: 1,
    food_name: '鱼香肉丝',
    food_price: 18.8,
    food_count: 1
  },{
    order_id: 2,
    food_name: '粗溜丸子',
    food_price: 26,
    food_count: 2
  },{
    order_id: 3,
    food_name: '杂粮煎饼',
    food_price: 12,
    food_count: 1
  }]
  build() {
    Row() {
      Column({space:20}) {
        ForEach(this.list, (item:FoodClass)=>{
          Row() {
            Text(item.food_name).TextStyle()
            Text(item.food_price.toFixed(2)).TextStyle()
            Text(item.food_count.toString()).TextStyle()
          }
          .height(40)
          .width('100%')
        })
        BottonCard({myList:$list}) // 记得传过去的数据要被state修饰
  // Link修饰的数据必须得是最外层的 State数据,如果没有被state修饰,后续ObjectLink 和Observerd会解决这个问题

      }
      .width('100%')
    }
    .height('100%')
  }
}

@Extend(Text)
function TextStyle() {
  .layoutWeight(1).textAlign(TextAlign.Center).fontSize(20)
}
// 食品类
class FoodClass {
  order_id: number = 0
  food_name:  string = ""
  food_price: number = 0
  food_count: number = 0
}
@Component
struct BottonCard {
  @Link
  myList:FoodClass[]
  build() {
    Button('更改菜品的数量')
      .onClick(() => {
        // map循环数组返回新数组,map中item代表数组中的元素,map会将其中的item组成一个新的数组
        this.myList = this.myList.map(item => {
          item.food_count++
          return item
        })
      })
  }
}

1.2、状态共享-后代组件

  如果我们的组件层级特别多,ArkTS支持跨组件传递状态数据来实现双向同步@Provide和 @Consume
  变量包括Object、class、string、number、boolean、enum 类型均支持@Provide和 @Consume
  例子:假设我们有三层组件,Index-Child-Grand, Index的数据不想经过Child而直接给到Grand可以使用该修饰器

1.2.1、通过相同的变量名绑定

@Entry
@Component
struct ProvideCase {
  @Provide money:number = 1000 // Provide跨组件提供数据,实现双向绑定,爷爷提供数据
  build() {
    Row() {
      Column({space:20}) {
        Text(`爷爷的钱:${this.money.toString()}`).fontSize(30)
        Divider().strokeWidth(3).color(Color.Red)
        Father()
      }
      .width('100%')
    }
    .height('100%')
  }
}

@Component
struct Father {
  @Consume money:number
  build() {
    Column() {
      Text('父亲组件').fontSize(30)
        .onClick(() => {
          this.money += 2
        })
      Divider().strokeWidth(3).color(Color.Green)
      GreateSon()
    }
  }
}

@Component
struct GreateSon {
  @Consume
  money:number // Consume跨组件接收数据,实现双向绑定
  build() {
    Text(`接收到爷爷的钱:${this.money.toString()}`)
      .fontSize(20)
      .onClick(() => {
        this.money -= 10
      })
  }
}

注意: 在不指定Provide名称的情况下,你需要使用相同的名字来定义和接收数据

1.2.2、通过相同的变量别名绑定

@Provide('key') 和 @Consume('key') key需要保持一致

@Provide('aa') money:number = 1000 // Provide跨组件提供数据,实现双向绑定,爷爷提供数据
@Consume('aa')  mon:number // Consume跨组件接收数据,实现双向绑定,Consume的状态变量不需要初始值

ArkTS所有内容都不支持深层数据(包过深层组件)更新 UI渲染

上一篇 下一篇

猜你喜欢

热点阅读