鸿蒙开发记录

170 阅读2分钟

注入UI样式

在鸿蒙开发中,Builder和BuilderParams是两个关键的工具,它们可以帮助我们更加高效地定义UI组件。

使用@Builder装饰器

@Builder装饰器允许我们自定义构建函数,这个函数可以在build()方法中使用,以生成具有特定样式和功能的UI组件。

示例:

@Builder function testButton(testError: boolean, text: string) {
  Button() {
    // 在这里定义按钮的样式和内容
  }    
}

build() {
  testButton(true, '测试页1');  // 创建第一个按钮
  testButton(false, '测试页2'); // 创建第二个按钮
}

在这个例子中,我们定义了一个testButton构建函数,它接受两个参数:testErrortext。通过在build()方法中调用这个函数,我们可以创建具有不同文本的按钮,同时保持样式的一致性。

使用BuilderParam装饰器

BuilderParam装饰器允许我们为组件定义可配置的参数,从而使组件更加灵活和可重用。

示例:

// XXXBaseView
class loadingViewParam {
  label: string = '';
}

@Builder
function loadingView($$: loadingViewParam) {
  Text($$.label)
    .width(400)
    .height(50)
    .backgroundColor('red')
}

@Component
@BuilderParam defaultLoadingView: ($$ : loadingViewParam) => void = loadingView;

// 业务View
@Builder pageLoadingView() {
    Text('page LoadingView').backgroundColor('black')
}

build() {
  Stack() {
    XXXView({
      launchModel: this.launchModel,
      defaultLoadingView: this.pageLoadingView
    })
  }
}

在这个例子中,我们定义了一个loadingView构建函数,它接受一个loadingViewParam参数,并使用这个参数来设置文本标签的样式和颜色。

子组件调用父组件方法

在某些情况下,子组件需要调用父组件的方法。为了确保在这些方法中正确地引用父组件的上下文,我们可以使用bind()方法。

示例:

// XXXView
export struct XXXView {
  @Link controller: XXXViewController; // 初始化控制器
  
  // 自定义错误页
  @BuilderParam customErrorView: ($$ : errorViewParam) => void = errorView;
}
private reload(): void{
    this.krnDelegate?.aboutToAppear()
}

aboutToAppear() {
  this.controller = new XXXViewController();
  this.controller.reload = this.reload.bind(this);
  // 使用bind确保在reload方法中正确引用XXXView的上下文
}

在这个例子中,我们在XXXView组件中定义了一个reload方法,并通过bind()方法确保在调用时this指向正确的上下文。

外部注入回调方法

定义接口

// XXXInterface

export interface XXXRootViewModule {
  didXXXRootViewAppear(viewModel: XXXViewModel, userInfo: Map<string, object>): void;
  didXXXRootViewLoadFailed(viewModel: XXXViewModel, error: Error, degrading: Boolean): void;
}

实现接口

export class XXXContainerStatus implements XXXRootViewModule {
  didXXXRootViewAppear(viewModel: XXXViewModel, userInfo:Map<string, object]): void {
    console.info('didXXXRootViewAppear, userInfo:', userInfo)
  }
  // ...省略其他方法
}

使用接口

// XXXView
export struct XXXView {
  krnViewStatusHandler?: XXXContainerStatus = new XXXContainerStatus()
}

// 调用方法
aboutToAppear() {
  this.krnViewStatusHandler?.didXXXRootViewAppear(this.krnViewModel!, userInfo!);
}

在这个例子中,我们定义了一个XXXContainerStatus类,它实现了XXXRootViewModule接口,并在XXXView组件中使用它来处理视图的加载和错误事件。

通过这种方式,我们可以确保在组件之间传递正确的上下文和参数,同时保持代码的清晰和可维护性。