赞
踩
每个UI组件需要定义为@Component struct对象,其内部必须包含一个且只能包含一个build(){}函数,用于绘制UI;struct之内、build()函数之外的地方用于存放数据。
@State:组件拥有的状态属性,当@State 装饰的变量更改时,组件会重新渲染更新 UI。
@Link:组件依赖于其父组件拥有的某些状态属性,当任何一个组件中的数据更新时,另一个组件的状态都会更新,父子组件重新渲染。
@Prop:类似@Link,但子组件所做的更改不会同步到父组件上,属于单向传递。
@Provide:作为数据的提供方,可以更新其子节点的数据,并触发页面渲染。
@Consume:在感知到@Provide 数据更新后,会触发当前自定义组件的重新渲染。
@StorageLink :组件通过使用@StorageLink(key)装饰的状态变量,与AppStorage 建立双向数据绑定,key为 AppStorage 中的属性键值。当创建包含@StorageLink 的状态变量的组件时,该状态变量的值将使用AppStorage 中的值进行初始化。在 UI 组件中对@StorageLink 的状态变量所做的更改将同步到AppStorage ,并从 AppStorage 同步到任何其他绑定实例中。
@StorageProp :组件通过使用@StorageProp(key)装饰的状态变量,将与 AppStorage 建立单向数据绑定,key 标识 AppStorage 中的属性键值。当创建包含@StoageProp 的状态变量的组件时,该状态变量的值将使用 AppStorage 中的值进行初始化。AppStorage 中的属性值的更改会导致绑定的 UI 组件进行状态更新。
装饰struct,页面的入口
装饰struct,表示该struct具有基于组件的能力
- @Entry
- @Component
- struct TestPage {
- build() {
- ……
- }
- }
- @Component
- export struct ComponentPage {
- @State count: number = 0
-
- private toggleClick() {
- this.count += 1
- }
-
- build() {
- Row() {
- Column({ space: 20 }) {
- Button(`这是子组件,${this.count}`)
- .fontSize(24)
- .onClick(this.toggleClick.bind(this))
- }
- .width('100%')
- }
- }
- }
- import { ComponentPage } from "./ComponentPage"
-
- @Entry
- @Component
- struct StatePage {
- @State count: number = 0
-
- private toggleClick() {
- this.count += 1
- }
-
- build() {
- Row() {
- Column({ space: 20 }) {
- Button(`这是父组件,当前值: ${this.count}`)
- .fontSize(24)
- .onClick(this.toggleClick.bind(this))
-
- //使用默认初始化值
- ComponentPage()
- //设置count初始值为:20
- ComponentPage({ count: 20 })
- }
- .width('100%')
- }.height('100%')
- }
- }
- @Component
- export struct ComponentPage {
- @Prop count: number
-
- private toggleClick() {
- this.count += 1
- }
-
- build() {
- Row() {
- Column({ space: 20 }) {
- Button(`这是子组件,${this.count}`)
- .fontSize(24)
- .onClick(this.toggleClick.bind(this))
- }
- .width('100%')
- }
- }
- }
- import { ComponentPage } from "./ComponentPage"
-
- @Entry
- @Component
- struct StatePage {
- @State count: number = 0
-
- private toggleClick() {
- this.count += 1
- }
-
- build() {
- Row() {
- Column({ space: 20 }) {
- Button(`这是父组件,当前值: ${this.count}`)
- .fontSize(24)
- .onClick(this.toggleClick.bind(this))
-
- ComponentPage({ count: this.count })
- }
- .width('100%')
- }.height('100%')
- }
- }
- @Component
- export struct ComponentPage {
- @Link count: number
-
- private toggleClick() {
- this.count += 1
- }
-
- build() {
- Row() {
- Column({ space: 20 }) {
- Button(`这是子组件,${this.count}`)
- .fontSize(24)
- .onClick(this.toggleClick.bind(this))
- }
- .width('100%')
- }
- }
- }
- import { ComponentPage } from "./ComponentPage"
-
- @Entry
- @Component
- struct StatePage {
- @State count: number = 0
-
- private toggleClick() {
- this.count += 1
- }
-
- build() {
- Row() {
- Column({ space: 20 }) {
- Button(`这是父组件,当前值: ${this.count}`)
- .fontSize(24)
- .onClick(this.toggleClick.bind(this))
-
- ComponentPage({ count: $count })
- }
- .width('100%')
- }.height('100%')
- }
- }
不同点 | @State | @Prop | @Link |
---|---|---|---|
装饰内容 | 基本数据类型,类,数组 | 基本数据类型 | 基本数据类型,类,数组 |
关联 | 不与其他控件关联 | 父@State -> 子@Prop 单向关联 | 父@State <-> 子@Link 双向关联 |
初始化时机 | 声明时 | 创建组件时由参数传入 | 创建组件时由参数传入 |
@Provide、@Consume
后代通过使用@Consume去获取@Provide提供的变量,建立在@Provide和@Consume之间的双向数据同步,与@State/@Link不同的是,前者可以在多层级的父子组件之间传递
在父组件中将数据多级传递给子组件,子子组件
- import { ProviderSonPage } from "./ProviderSonPage"
-
- @Entry
- @Component
- struct ProviderPage {
- @State message: string = '父类A'
-
- build() {
- Row() {
- Column() {
- Text(this.message).fontSize(50).fontColor(Color.Red)
- .onClick(() => {
- //点击文字 进行切换
- this.message = this.message === '父类A' ? '父类B' : '父类A'
- })
- //调用子组件
- ProviderSonPage({ sonMsg: $message })
- }
- .width('100%')
- }
- .height('100%')
- }
- }
- import { ProviderGrandSonPage } from "./ProviderGrandSonPage"
-
- @Component
- export struct ProviderSonPage {
- @Link sonMsg: string
-
- build() {
- Column() {
- Text(this.sonMsg).fontSize(30).fontColor(Color.Green)
- .onClick(() => {
- this.sonMsg = '我是子类'
- })
- //调用孙子组件:子类的子类
- ProviderGrandSonPage({ grandSonMsg: $sonMsg })
- }
- }
- }
- @Component
- export struct ProviderGrandSonPage {
- @Link grandSonMsg: string
-
- build() {
- Column() {
- Text(this.grandSonMsg).fontSize(20).fontColor(Color.Blue)
- .onClick(() => {
- this.grandSonMsg = '我是子类的子类'
- })
- }
- }
- }
使用发布者Provide和订阅者Consume可以直接传递到子子组件
- import { ProviderSonPage } from "./ProviderSonPage"
-
- @Entry
- @Component
- struct ProviderPage {
- @Provide('Mes') message: string = '父类A'
- //也可以写成@Provide message: string = '父类A'
- build() {
- Row() {
- Column() {
- Text(this.message).fontSize(50).fontColor(Color.Red)
- .onClick(() => {
-
- this.message = this.message === '父类A' ? '父类B' : '父类A'
- })
- //调用子组件时就不再需要传递参数
- ProviderSonPage()
- }
- .width('100%')
- }
- .height('100%')
- }
- }
- import { ProviderGrandSonPage } from "./ProviderGrandSonPage"
-
- @Component
- export struct ProviderSonPage {
- @Consume('Mes') sonMsg:string
-
- build() {
- Column() {
- Text(this.sonMsg).fontSize(30).fontColor(Color.Green)
- .onClick(() => {
- this.sonMsg = '我是子类'
- })
- //调用子组件时就不再需要传递参数
- ProviderGrandSonPage()
- }
- }
- }
- @Component
- export struct ProviderGrandSonPage {
- @Consume('Mes') grandSonMsg:string
- //也可以写成@Consume message:string
-
- build() {
- Column() {
- Text(this.grandSonMsg).fontSize(20).fontColor(Color.Blue)
- .onClick(() => {
- this.grandSonMsg = '我是子类的子类'
- })
- }
- }
- }
效果图:
@Watch:使用观察者模式的装饰器,但该装饰器不是触发变量变化,而是绑定一个函数,当@Watch变量变化时,调用该函数
- @Component
- export struct TotalViewPage {
- @Prop @Watch('onCountUpdated') count: number;
- @State total: number = 0;
- // @Watch 回调
- onCountUpdated(propName: string): void {
- this.total += this.count;
- }
-
- build() {
- Text(`Total: ${this.total}`)
- }
- }
- import {TotalViewPage} from "./TotalViewPage"
-
- @Entry
- @Component
- struct CountModifierPage {
- @State count: number = 0;
-
- build() {
- Column() {
- Button('add to basket')
- .onClick(() => {
- this.count++
- })
- TotalViewPage({ count: this.count })
- }
- }
- }
- export class PurchaseItem {
- static NextId: number = 0;
- public id: number;
- public price: number;
-
- constructor(price: number) {
- this.id = PurchaseItem.NextId++;
- this.price = price;
- }
- }
- import {PurchaseItem} from "./PurchaseItem"
-
- @Component
- export struct BasketViewer {
- @Link @Watch('onBasketUpdated') shopBasket: PurchaseItem[];
- @State totalPurchase: number = 0;
-
- updateTotal(): number {
- let total = this.shopBasket.reduce((sum, i) => sum + i.price, 0);
- // 超过100欧元可享受折扣
- if (total >= 100) {
- total = 0.9 * total;
- }
- return total;
- }
- // @Watch 回调
- onBasketUpdated(propName: string): void {
- this.totalPurchase = this.updateTotal();
- }
- build() {
- Column() {
- ForEach(this.shopBasket,
- (item) => {
- Text(`Price: ${item.price.toFixed(2)} €`)
- },
- item => item.id.toString()
- )
- Text(`Total: ${this.totalPurchase.toFixed(2)} €`)
- }
- }
- }
- import {BasketViewer} from "./BasketViewer"
- import {PurchaseItem} from "./PurchaseItem"
-
- @Entry
- @Component
- struct BasketModifierPage {
- @State shopBasket: PurchaseItem[] = [];
- build() {
- Column() {
- Button('Add to basket')
- .onClick(() => {
- this.shopBasket.push(new PurchaseItem(Math.round(100 * Math.random())))
- })
- BasketViewer({ shopBasket: $shopBasket })
- }
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。