HarmonyOS鸿蒙Next中碰到一个很奇怪的问题关于WithTheme的,使用@LocalBuilder它样式不更新,使用@Builder它的样式更新但是this指向又有问题

HarmonyOS鸿蒙Next中碰到一个很奇怪的问题关于WithTheme的,使用@LocalBuilder它样式不更新,使用@Builder它的样式更新但是this指向又有问题

点击按钮切换样式,builder1是@Builder它的颜色样式更新了,但是由于this指向的问题它拿不到样式的颜色值(builder1是按钮上显示的是undefined);

builder2是@LocalBuilder它的颜色样式没有更新,由于this指向没问题它拿到了样式的颜色值。

这个builder1和builder2都属于WithTheme下的子组件,按道理来讲builder1和builder2都应该更新样式的


```typescript
import { CustomColors, CustomTheme } from '[@kit](/user/kit).ArkUI';

class AppColors implements CustomColors {
  fontPrimary: ResourceColor = Color.Blue;
  backgroundEmphasize: ResourceColor = Color.Blue;
}

class AppColorsSec implements CustomColors {
  fontPrimary: ResourceColor = Color.Orange;
  backgroundEmphasize: ResourceColor = Color.Orange;
}

class AppTheme implements CustomTheme {
  public colors: AppColors = new AppColors();
}

class AppThemeSec implements CustomTheme {
  public colors: AppColors = new AppColorsSec();
}

[@Entry](/user/Entry)
[@Component](/user/Component)
struct DisplayPage {
  [@State](/user/State) customTheme: CustomTheme = new AppTheme();
  message: string = '设置应用局部页面自定义主题风格';
  count = 0;

  build() {
    WithTheme({ theme: this.customTheme }) {
      Column() {
        Text('WithTheme')
          .fontSize(30)
          .margin({ bottom: 10 })
        Text(this.message)
          .margin({ bottom: 10 })
        Button('change theme').onClick(() => {
          this.count++;
          if (this.count > 1) {
            this.count = 0;
          }
          switch (this.count) {
            case 0:
              this.customTheme = new AppTheme();
              break;
            case 1:
              this.customTheme = new AppThemeSec();
              break;
          }
        })

        MyComponent({
          view1: this.builder1,
          view2: this.builder2,
        }).margin({ top: 30 })

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

  [@Builder](/user/Builder)
  builder1() {
    Column() {
      Text('builder1')
        .fontSize(30)
        .margin({ top: 30, bottom: 10 })
      Button(`backgroundEmphasize:${this.customTheme?.colors?.backgroundEmphasize}`)
    }
    .width('100%')
  }

  [@LocalBuilder](/user/LocalBuilder)
  builder2() {
    Column() {
      Text('builder2')
        .fontSize(30)
        .margin({ top: 30, bottom: 10 })
      Button(`backgroundEmphasize:${this.customTheme?.colors?.backgroundEmphasize}`)
    }
    .width('100%')
  }
}

[@Component](/user/Component)
struct MyComponent {
  [@BuilderParam](/user/BuilderParam) view1: () => void
  [@BuilderParam](/user/BuilderParam) view2: () => void

  build() {
    Column() {
      this.view1()
      this.view2()
    }.width('100%')
  }
}

更多关于HarmonyOS鸿蒙Next中碰到一个很奇怪的问题关于WithTheme的,使用@LocalBuilder它样式不更新,使用@Builder它的样式更新但是this指向又有问题的实战教程也可以访问 https://www.itying.com/category-93-b0.html

4 回复
<MyComponent> view1: () => { this.builder1()}, view2: () => { this.builder2()}, ).margin({ top: 30 })

使用箭头函数呢?

更多关于HarmonyOS鸿蒙Next中碰到一个很奇怪的问题关于WithTheme的,使用@LocalBuilder它样式不更新,使用@Builder它的样式更新但是this指向又有问题的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


箭头函数和@LocalBuilder的效果是一样的,this指向没问题样式就有问题,样式没问题this指向就错了。

在HarmonyOS Next中,@LocalBuilder@Builder的差异在于作用域。@LocalBuilder不会跟随主题更新,因为它绑定的是组件初始状态。@Builder能响应主题变化,但会丢失原始组件上下文(this)。这是设计机制差异,不是bug。如需同时保留this引用和主题响应,可尝试将this显式传递给@Builder参数。两种装饰器的this绑定逻辑在ArkUI框架层已固定。

这是一个关于HarmonyOS Next中WithTheme组件与Builder/LocalBuilder作用域的问题。主要区别在于:

  1. @Builder是全局构建器,会导致this指向丢失,因此虽然样式能更新,但无法通过this访问到customTheme实例。

  2. @LocalBuilder是局部构建器,能正确保持this指向,但由于其构建过程发生在父组件初始化阶段,导致无法响应WithTheme的更新。

解决方案:

  • 对于需要访问this的场景,建议使用@LocalBuilder并通过参数传递theme值
  • 或者将Builder内容直接内联到WithTheme作用域内,避免使用构建器

示例修改:

[@LocalBuilder](/user/LocalBuilder)
builder2(theme: CustomTheme) {
  Column() {
    Text('builder2')
    Button(`backgroundEmphasize:${theme?.colors?.backgroundEmphasize}`)
  }
}

这样既能保持this指向,又能响应主题更新。

回到顶部