#HarmonyOS篇:学习UI规范基本语法&&学习UI范式装填管理V1&&学习UI范式装填管理V2&&学习UI范式渲染控制

学习UI规范基本语法

自定义组件
事件生命类型
ts 复制代码
// 声明
submit :() => void = () =>{
this.num++
}
// 传递  
Test1({num:this.num,submitArrow: this.submit })
//接收
submitArrow?: () => void
根节点容器怎么用
ts 复制代码
@Entry
@Component
struct MyComponent {
  build() {
    // 根节点唯一且必要,必须为容器组件
    Row() {
      ChildComponent()
    }
  }
}

@Component
struct ChildComponent {
  build() {
    // 根节点唯一且必要,可为非容器组件
    Image('test.jpg')
  }
}
自定义组件生命周期

aboutToAppear组件即将出现时,在执行器build函数之前。

onDidBuild触发build函数执行之后回调。

aboutToDisappear函数在自定义组件析构销毁之前执行。

组件扩展

@Builder 自定义构建函数 @Builder装饰器用于封装可复用的UI结构

@LocalBuilder 维持组件关系

ts 复制代码
// 返回child
@Component
struct Child {
  label: string = 'Child';
  @BuilderParam customBuilderParam: () => void;

  build() {
    Column() {
      this.customBuilderParam()
    }
  }
}

@Entry
@Component
struct Parent {
  label: string = 'Parent';

  @Builder componentBuilder() {
    Text(`${this.label}`)
  }

  // @LocalBuilder componentBuilder() {
  //   Text(`${this.label}`)
  // }

  build() {
    Column() {
      Child({ customBuilderParam: this.componentBuilder })
    }
  }
} 
---------------------------------------------------------
// 返回parent
@Component
struct Child {
  label: string = 'Child';
  @BuilderParam customBuilderParam: () => void;

  build() {
    Column() {
      this.customBuilderParam()
    }
  }
}

@Entry
@Component
struct Parent {
  label: string = 'Parent';

  // @Builder componentBuilder() {
  //   Text(`${this.label}`)
  // }

  @LocalBuilder componentBuilder() {
    Text(`${this.label}`)
  }

  build() {
    Column() {
      Child({ customBuilderParam: this.componentBuilder })
    }
  }
}

@BuilderParam--@BuilderParam用于装饰指向@Builder方法的变量,开发者可以在初始化自定义组件时,使用不同的方式(如参数修改、尾随闭包、借用箭头函数等)对@BuilderParam装饰的自定义构建函数进行传参赋值。

@BuilderParam装饰的方法只能被自定义构建函数(@Builder装饰的方法)初始化。

使用@BuilderParam隔离多组件对@Builder跳转逻辑的调用

ts 复制代码
@Component
struct Child {
  @Builder
  customBuilder() {
  }

  @BuilderParam customBuilderParam: () => void = this.customBuilder;

  build() {
    Column() {
      this.customBuilderParam()
    }
  }
}

@Entry
@Component
struct Parent {
  @Builder
  componentBuilder() {
    Text(`Parent builder `)
  }

  build() {
    Column() {
      Child({ customBuilderParam: this.componentBuilder })
    }
  }
}

wrapBuilder

ts 复制代码
@Builder
function MyBuilder(value: string, size: number) {
  Text(value)
    .fontSize(size)
}

@Builder
function YourBuilder(value: string, size: number) {
  Text(value)
    .fontSize(size)
    .fontColor(Color.Pink)
}

const builderArr: WrappedBuilder<[string, number]>[] = [wrapBuilder(MyBuilder), wrapBuilder(YourBuilder)];


@Entry
@Component
struct Index {
  @Builder
  testBuilder() {
    ForEach(builderArr, (item: WrappedBuilder<[string, number]>) => {
      item.builder('Hello World', 30)
    }

    )
  }

  build() {
    Row() {
      Column() {
        this.testBuilder()
      }
      .width('100%')
    }
    .height('100%')
  }
}
一些装饰器

@Styles自定义组件重用样式

@Expend组件扩展示样式

stateStyles:多态样式

ts 复制代码
@Component
struct Child {
  label: string = 'Child';
  @BuilderParam customBuilderParam: () => void;

  build() {
    Column() {
      this.customBuilderParam()
    }
  }
}
@Extend(Text)
function fancy() {
  .fontColor(Color.White)

}

@Entry
@Component
struct Parent {
  @Styles
  red() {
    .width(200)
    .background(Color.Red)
  }
  label: string = 'Parent';

  // @Builder componentBuilder() {
  //   Text(`${this.label}`)
  // }

  @LocalBuilder componentBuilder() {
    Text(`${this.label}`)
  }

  build() {
    Column() {
      Text('1234').red().fancy()
      Child({ customBuilderParam: this.componentBuilder })
      Button('Button1')
        .stateStyles({
          focused: {
            .backgroundColor('#ffffeef0')
          },
          pressed: {
            .backgroundColor(Color.Red)
          },
          normal: {
            .backgroundColor('#ff2787d9')
          }
        })
        .margin(20)
    }
  }
}

学习UI范式装填管理V1

@State

@Prop

@Link

@Provide @Consume

@Observed @ObjectLink

@ObjectLink接收@State传递built-in类型和普通class对象,可以观察其API调用和第一层变化,无需额外添加@Observed装饰。因为@State等状态变量装饰器,会给对象(外层对象)添加一层"代理"包装,其功能等同于添加@Observed装饰。

ts 复制代码
@Observed
class Book {
   name:string;
   count:number
  constructor(name:string,count:number) {
    this.name = name
    this.count= count
  }
}
@Observed
class Bag {
  book:Book;
  constructor(book:Book) {
    this.book = book
  }
}
@Entry
@Component
struct Index {
  @Provide('aa') a:string = 'provide'
  @State book:Book = new Book('小红书',12)
  @State bag: Bag = new Bag(new Book('JS',12));
  build() {
    Column() {
      Text(this.book.name)
      Text(this.bag.book.name)
      Test1({book:this.book})
      Button('change book.name')
        .width(320)
        .margin(10)
        .onClick(() => {
          this.book = new Book('咸鱼',13)
          // this.book.name = 'C++';
          // this.book.count++;
          // this.bag.book.name = 'TS';
          // this.bag.book.count ++
        })
      Divider()
      Test2({book:this.bag.book})
    }
  }
}


@Component
struct Test1 {
  @ObjectLink book:Book
  build() {
    Column() {
      Text(this.book.count.toString())
      // Test2()
      Button('改变book').onClick((event: ClickEvent) => {
        this.book.count++

      })
    }
  }
}

@Component
struct Test2 {
  @Consume('aa') a:string
  @ObjectLink book:Book
  build() {
    Column() {
      Text('test2----'+ this.book.count)
      Button('++').onClick((event: ClickEvent) => {
        this.book.count++
      })
    }
  }
}

LocalStorage 页面级UI状态存储 LocalStorageProp、LocalStorageLink

ts 复制代码
class Data {
  code: number;

  constructor(code: number) {
    this.code = code;
  }
}
// 创建新实例并使用给定对象初始化
let para: Record<string, number> = { 'PropA': 11 };
let storage: LocalStorage = new LocalStorage(para);
storage.setOrCreate('PropB', new Data(50));

@Component
struct Child {
  // @LocalStorageLink变量装饰器与LocalStorage中的'PropA'属性建立双向绑定
  @LocalStorageLink('PropA') childLinkNumber: number = 1;
  // @LocalStorageLink变量装饰器与LocalStorage中的'PropB'属性建立双向绑定
  @LocalStorageLink('PropB') childLinkObject: Data = new Data(0);

  build() {
    Column({ space: 15 }) {
      // 更改将同步至LocalStorage中的'PropA'以及Parent.parentLinkNumber
      Button(`Child from LocalStorage ${this.childLinkNumber}`)
        .onClick(() => {
          this.childLinkNumber += 1;
        })
      // 更改将同步至LocalStorage中的'PropB'以及Parent.parentLinkObject.code
      Button(`Child from LocalStorage ${this.childLinkObject.code}`)
        .onClick(() => {
          this.childLinkObject.code += 1;
        })
    }
  }
}
// 使LocalStorage可从@Component组件访问
@Entry(storage)
@Component
struct Parent {
  // @LocalStorageLink变量装饰器与LocalStorage中的'PropA'属性建立双向绑定
  @LocalStorageLink('PropA') parentLinkNumber: number = 1;
  // @LocalStorageLink变量装饰器与LocalStorage中的'PropB'属性建立双向绑定
  @LocalStorageLink('PropB') parentLinkObject: Data = new Data(0);

  build() {
    Column({ space: 15 }) {
      // 由于LocalStorage中PropA已经被初始化,因此this.parentLinkNumber的值为47
      Button(`Parent from LocalStorage ${this.parentLinkNumber}`)
        .onClick(() => {
          this.parentLinkNumber += 1;
        })
      // 由于LocalStorage中PropB已经被初始化,因此this.parentLinkObject.code的值为50
      Button(`Parent from LocalStorage ${this.parentLinkObject.code}`)
        .onClick(() => {
          this.parentLinkObject.code += 1;
        })
      // @Component子组件自动获得对Parent LocalStorage实例的访问权限。
      Child()
    }
  }
}

// 应用全局的UI状态

AppStorage

@StoragePop单向

@StorageLink双向

不会通知UI刷新

ts 复制代码
AppStorage.set<number>('propA', 100);
ts 复制代码
class Data {
  code: number;

  constructor(code: number) {
    this.code = code;
  }
}

AppStorage.setOrCreate('propA', 47);
AppStorage.setOrCreate('propB', new Data(50));
let storage = new LocalStorage();
storage.setOrCreate('linkA', 48);
storage.setOrCreate('linkB', new Data(100));

@Entry()
@Component
struct Index {
  @StorageLink('propA') storageLink: number = 1;
  @StorageProp('propA') storageProp: number = 1;
  @StorageLink('propB') storageLinkObject: Data = new Data(1);
  @StorageProp('propB') storagePropObject: Data = new Data(1);

  build() {
    Column({ space: 20 }) {
      // @StorageLink与AppStorage建立双向联系,更改数据会同步回AppStorage中key为'propA'的值
      Text(`storageLink ${this.storageLink}`)
        .onClick(() => {
          this.storageLink += 1;
        })

      // @StorageProp与AppStorage建立单向联系,更改数据不会同步回AppStorage中key为'propA'的值
      // 但能被AppStorage的set/setorCreate更新值
      Text(`storageProp ${this.storageProp}`)
        .onClick(() => {
          this.storageProp += 1;
        })

      // AppStorage的API虽然能获取值,但是不具有刷新UI的能力,日志能看到数值更改
      // 依赖@StorageLink/@StorageProp才能建立起与自定义组件的联系,刷新UI
      Text(`change by AppStorag11e: ${AppStorage.get<number>('propA')}`)
        .onClick(() => {
          console.info(`Appstorage.get: ${AppStorage.get<number>('propA')}`);
          AppStorage.set<number>('propA', 100);
        })

      Text(`storageLinkObject ${this.storageLinkObject.code}`)
        .onClick(() => {
          this.storageLinkObject.code += 1;
        })

      Text(`storagePropObject ${this.storagePropObject.code}`)
        .onClick(() => {
          this.storagePropObject.code += 1;
        })
    }
  }
}

// 持久话存储UI状态

PersisitentStorage

PersistentStorage.persistProp('aProp', 47);

ts 复制代码
PersistentStorage.persistProp('aProp', 47);

@Entry
@Component
struct Index {
  @State message: string = 'Hello World';
  @StorageLink('aProp') aProp: number = 48;

  build() {
    Row() {
      Column() {
        Text(this.message)
        // 应用退出时会保存当前结果。重新启动后,会显示上一次的保存结果
        // 未修改时默认值为47
        Text(`${this.aProp}`)
          .onClick(() => {
            this.aProp += 1;
          })
      }
    }
  }
}

@Component

Environment 设备环境查询

ts 复制代码
import { UIAbility } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';

export default class EntryAbility extends UIAbility {
  onWindowStageCreate(windowStage: window.WindowStage) {
    windowStage.loadContent('pages/Index');
    let window = windowStage.getMainWindow();
    window.then(window => {
      let uiContext = window.getUIContext();
      uiContext.runScopedTask(() => {
        Environment.envProp('languageCode', 'en');
      });
    });
  }
}

@Watch

ts 复制代码
@Component
struct TotalView {
  @Prop @Watch('onCountUpdated') count: number = 0;
  @State total: number = 0;
  // @Watch 回调
  onCountUpdated(propName: string): void {
    this.total += this.count;
  }

  build() {
    Text(`Total: ${this.total}`)
  }
}

@Entry
@Component
struct CountModifier {
  @State count: number = 0;

  build() {
    Column() {
      Button('add to basket')
        .onClick(() => {
          this.count++
        })
      TotalView({ count: this.count })
    }
  }
}

系统组件双向同步 **$$运算符为系统组件提供TS变量的引用,使得TS变量和系统组件的内部状态保持同步。** ```ts @Entry @Component struct Index { @State text: string = ''; controller: TextInputController = new TextInputController(); build() { Column({ space: 20 }) { Text(this.text) TextInput({ text: $$this.text, placeholder: 'input your word...', controller: this.controller }) .placeholderColor(Color.Grey) .placeholderFont({ size: 14, weight: 400 }) .caretColor(Color.Blue) .width(300) } .width('100%') .height('100%') .justifyContent(FlexAlign.Center) } } ``` @Track class对象属性级更新---------避免无用渲染 @Track是class对象的属性装饰器。当一个class对象是状态变量时,@Track装饰的属性发生变化,只会触发该属性关联的UI更新;如果class类中使用了@Track装饰器,则未被@Track装饰器装饰的属性不能在UI中使用,如果使用,会发生运行时报错。 #### 学习UI范式装填管理V2 @Local @Param @Once @Event @provider @Consumer @ObServedV2 @Trace @Computed @Monitor @ReusableV2 @ComponentV2 AppStorageV2 #### 学习UI范式渲染控制

相关推荐
前端世界3 小时前
鸿蒙分布式权限管理实战指南:架构原理 + 可运行 Demo
分布式·架构·harmonyos
前端世界3 小时前
鸿蒙分布式通信安全实践:中间人攻击原理与防御实现
分布式·华为·harmonyos
12 小时前
鸿蒙——通知
华为·harmonyos·
周胡杰16 小时前
鸿蒙preferences单多例使用,本地存储类
缓存·华为·harmonyos·preferences·鸿蒙本地存储
IvanCodes16 小时前
[鸿蒙2025领航者闯关] 共享终端的隐形守护者:基于 HarmonyOS 6 的全链路隐私闭环实战
华为·harmonyos·鸿蒙
芒鸽21 小时前
鸿蒙PC上FFmpeg+Electron的Encode Smoke(P2) 排错实录:从“无法播放/时长为 0”到“保留画面且转完整时长”
ffmpeg·electron·harmonyos
2501_944449081 天前
帮助中心页面 Cordova&OpenHarmony 混合开发实战
harmonyos
搬砖的kk1 天前
在鸿蒙PC上开发鸿蒙应用:一场从协同到高效的技术之旅
华为·harmonyos
Tipriest_1 天前
华为鸿蒙/OpenHarmony 的设备调试工具hdc介绍
华为·harmonyos·hdc