ArkTs-组件状态管理

管理组件拥有的状态

@State修饰符

  • @State 装饰的变量是组件内部的状态数据,当这些状态数据被修改时,将会调用所在组件的 build() 方法刷新UI。
  • 支持多种数据类型:允许 class 、 number 、 boolean 、 string 强类型的按值和按引用类型。允许这些强类型构成的数组,即Array、Array、Array、Array。不允许 object 和 any。
  • 内部私有:标记为 @State 的属性是私有变量,只能在组件内访问。
  • 需要本地初始化:必须为所有 @State 变量分配初始值,将变量保持未初始化可能导致框架行为未定义,初始值需要是有意义的值,比如设置 class 类型的值为 null 就是无意义的,会导致编译报错。

使用样例:

@Entry
@Component 
struct ComponentTest {

  @State date: string = "时间:" + new Date().getTime(); // data变化会触发build方法执行

  build() {
    Column({space: 10}) {

      Text(`父组件【${this.date}`)                     // 显示时间
        .fontSize(20)
        .backgroundColor(Color.Pink)

      Item()                                            // 子组件
      Item()                                            // 子组件

      Button('更新时间')
        .onClick(() => {
          this.date = "时间:" + new Date().getTime();   // 点击按钮,date变化,会触发build方法执行
        })
    }
    .width('100%')
    .height('100%')
    .padding(10)
  }
}

// 自定义子组件
@Component struct Item {
  @State time: string = "时间:" + new Date().getTime();

  build() {
    Text(`子组件【${this.time}`)
      .fontSize(20)
      .backgroundColor(Color.Grey)
      .onClick(() => {
        this.time = "时间:" + new Date().getTime();     // 点击更新时间,执行build方法
      })
  }
}

@Prop修饰符

  • @Prop与@State有相同的语义,但初始化方式不同,@Prop装饰的变量可以和父组件的@State变量建立单向的数据绑定。即@Prop修饰的变量必须使用其父组件提供的@State变量进行初始化,允许组件内部修改@Prop变量值但更改不会通知父组件。
  • 支持简单数据类型:仅支持 number 、 string 、 boolean 简单类型;
  • 内部私有:标记为 @Prop 的属性是私有变量,只能在组件内访问。
  • 不支持内部初始化:在创建组件的新实例时,必须将值传递给 @Prop 修饰的变量进行初始化,不支持在组件内部进行初始化。

使用样例:

@Entry
@Component
struct ComponentTest {
  @State date: string = "时间:" + new Date().getTime();

  build() {
    Column({ space: 10 }) {

      Text(`父组件【${this.date}`)
        .fontSize(20)
        .backgroundColor(Color.Pink)

      Item({ time: this.date }) // 必须初始化子组件的time字段
      Item({ time: this.date }) // 必须初始化子组件的time字段

      Button('更新时间')
        .onClick(() => {
          this.date = "时间:" + new Date().getTime(); // 父组件的更改影响子组件
        })
    }
    .width('100%')
    .height('100%')
    .padding(10)
  }
}

@Component
struct Item {
  @Prop time: string; // 不允许本地初始化
  build() {
    Text(`子组件【${this.time}`)
      .fontSize(20)
      .backgroundColor(Color.Grey)
      .onClick(() => {
        this.time = "时间:" + new Date().getTime(); // 子组件的更改不影响父组件
      })
  }
}

@Link修饰符

  • @Link装饰的变量可以和父组件建立双向同步关系,子组件中@Link装饰变量的修改会同步给父组件中建立双向数据绑定的数据源,父组件的更新也会同步给@Link装饰的变量。
  • 支持多种数据类型: @Link 变量的值与 @State 变量的类型相同,即 class 、 number 、 string 、 boolean 或这些类型的数组。
  • 内部私有:标记为 @Link 的属性是私有变量,只能在组件内访问。
  • 不支持内部初始化:在创建组件的新实例时,必须将值传递给 @Link 修饰的变量进行初始化,不支持在组件内部进行初始化。初始化使用 $ 符号,例如:$propertiesName。

样例:

@Entry 
@Component 
struct ComponentTest {
  @State date: string = "时间:" + new Date().getTime(); // 定义@State变量

  build() {
    Column({space: 10}) {

      Text(`父组件【${this.date}`)
        .fontSize(20)
        .backgroundColor(Color.Pink)

      Item({time: $date})                               // 初始化子组件time属性使用$符号
      Item({time: $date})                               // 初始化子组件time属性使用$符号

      Button('更新时间')
        .onClick(() => {
          this.date = "时间:" + new Date().getTime();   // 变更date,子组件的对应属性也变化
        })
    }
    .width('100%')
    .height('100%')
    .padding(10)
  }
}

@Component struct Item {
  @Link time: string;
  build() {
    Text(`子组件【${this.time}`)
      .fontSize(20)
      .backgroundColor(Color.Grey)
      .onClick(() => {
        this.time = "时间:" + new Date().getTime();     // 变更time,父组件的对应属性也变化
      })
  }
}

@Provide/@Consume装饰器:与后代组件双向同步

  • @Provide/@Consume装饰的变量用于跨组件层级(多层组件)同步状态变量,可以不需要通过参数命名机制传递,通过alias(别名)或者属性名绑定。
  • 后代通过使用@Consume去获取@Provide提供的变量,建立在@Provide和@Consume之间的双向数据同步,与@State/@Link不同的是,前者可以在多层级的父子组件之间传递。
  • @Provide和@Consume可以通过相同的变量名或者相同的变量别名绑定,建议类型相同,否则会发生类型隐式转换,从而导致应用行为异常。
    @Watch修饰符
  • @Watch 用来监听状态变量的变化,当它修饰的状态变量发生变更时,回调相应的方法。

样例:

@Entry 
@Component 
struct WatchTest {

  @State @Watch("onBasketUpdated") shopBasket: Array<number> = [7, 12, 47, 3];
  @State totalPurchase: number = 0;

  updateTotal(): number {
    let sum = 0;
    this.shopBasket.forEach((i) => {
      sum += i;
    });
    // 计算新的购物篮总价值,如果超过100RMB,则适用折扣
    this.totalPurchase = (sum < 100) ? sum : 0.9 * sum;
    return this.totalPurchase;
  }

  onBasketUpdated(propName: string): void {
    this.updateTotal();
  }

  build() {
    Column({space: 10}) {
      Text(`${this.totalPurchase}`)
        .fontSize(30)

      Button("add to basket")
        .onClick(() => {
          this.shopBasket.push(Math.round(100 * Math.random()))
        })
    }
    .width("100%")
    .height("100%")
    .padding(10)
  }
}
ArkTS 是一种基于 TypeScript 的构建工具,用于自动化前端项目的任务管理、依赖管理和代码转换等操作。它结合了 Webpack 和 Babel 等其他工具的优点,提供了一个强大的配置系统,适用于构建复杂的现代前端应用程序。 当你提到“ArkTS,父组件获取子组件状态”,实际上这个描述与 ArkTS 并无直接关联,因为 ArkTS 主要是作为构建过程中的工具来使用的,并不会直接处理组件间的通信。但是,如果你想了解如何在 React 这样的框架中,通过类似的概念来实现父组件获取子组件状态的功能,我可以为你提供一些建议: ### 使用 React React 提供了几种基本的方式来让父组件访问子组件状态: #### 1. **stateless functional components (SFC) + props** 在这种模式下,子组件通常是无状态的函数组件,它们从 `props` 接收数据并将其显示出来。父组件可以直接将需要传递给子组件的数据作为 `props` 来传入。 ```javascript // 父组件 function ParentComponent() { return ( <ChildComponent name="John" /> ); } // 子组件 function ChildComponent(props) { return <div>{props.name}</div>; } ``` #### 2. **stateful component with state** 在这个模型中,子组件可以有自己的状态,通常通过类组件状态化的函数组件来实现。然后父组件可以通过回调函数或生命周期方法来更新子组件状态。 ```javascript class ChildComponent extends React.Component { constructor(props) { super(props); this.state = { myState: 'initial' }; } updateMyState(newState) { // 更新子组件状态 this.setState(newState); } render() { return ( <div> State: {this.state.myState} {/* 更新状态时调用父组件的函数 */} Update state: <button onClick={() => this.props.updateState(this.state)}>Update</button> </div> ); } } // 父组件 function ParentComponent() { const [childState, setChildState] = useState('initial'); return ( <> {/* 向子组件提供更新状态的方法 */} <ChildComponent updateState={setChildState} /> {/* 显示当前子组件状态 */} Current state: {childState} </> ); } ``` #### 3. **useRef hook** 对于更现代的实践,可以使用 React Hooks 中的 `useRef` 来存储子组件状态引用,然后在父组件中通过这个引用去修改子组件状态。 ```javascript import { useRef } from 'react'; function ParentComponent() { const childRef = useRef(null); function setState(newState) { if (childRef.current) { childRef.current.setState(newState); } } return ( <ChildComponent ref={childRef} /> /* 在这里可以监听或使用来自子组件状态 */ ); } function ChildComponent({ ref }) { const [myState, setMyState] = useState('initial'); useEffect(() => { // 直接在这里访问或更新子组件状态 console.log(myState); }, [myState]); // 如果有状态改变,你可以在这里触发外部状态变化 // setMyState(nextState); } ``` ### 关联问题: 1. **如何在 React 中管理组件间的状态共享**? 2. **React 组件状态管理最佳实践是什么**? 3. **在 React 应用中引入 Redux 或 MobX 进行复杂状态管理的好处是什么**?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值