【每日学点HarmonyOS Next知识】页面传参、弹窗禁止点击空白关闭、双向绑定数据报错、销毁自定义组件、图片设置模糊

1、HarmonyOS window.setUIContent 时怎么传参数给对应的Page?

window.setUIContent怎么传参数给WindowContent呢

用如下接口试一下:loadContent(path: string, storage: LocalStorage): Promise<void>根据当前工程中某个页面的路径为窗口加载具体页面内容,通过LocalStorage传递状态属性给加载的页面,使用Promise异步回调。具体文档如下:https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-window-V5#loadcontent9

2、HarmonyOS 自定义弹窗如何禁止点击空白处关闭功能?

参考文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-references-V5/js-apis-promptaction-V5#ZH-CN_TOPIC_0000001884757698__basedialogoptions11

3、HarmonyOS HSP包中Slider组件使用$$双向绑定数据编译时报错?

在HSP包中的页面,Slider组件使用双向绑定数据会在编译时报错Canotfindname this’,如果放在Hap包中可以正常使用,页面代码如下

@Entry
@Component
struct SliderPage {
  @State value: number = 0
  build() {
    RelativeContainer() {
      // 这里使用$$双向绑定会在编译时报错
      Slider({value: $$this.value, step: 0.01})
        .id('slider')
        .alignRules({
          center: { anchor: '__container__', align: VerticalAlign.Center },
          middle: { anchor: '__container__', align: HorizontalAlign.Center }
        })
        .blockSize({ width: '20', height: '20' })
        .onChange((value, mode) => {
          if(mode === SliderChangeMode.End) {
            console.log('end')
            setTimeout(() => {
              console.log('settimeout')
              this.value = 90
              console.log(`this.value ${this.value}`)
            }, 1000)
          }
          console.log(`${value}`)
        })
    }
    .height('100%')
    .width('100%')
  }
}

@State修饰的变量不需要操作了,直接使用this.value即可,去除操作了,直接使用this.value即可,去除尝试,或者使用@Link

4、HarmonyOS 如何主动销毁自定义组件?

如何主动销毁自定义组件?Demo这个组件里添加一个销毁方法:destroy,如何实现这个方法来销毁组件本身。

@Component
struct Demo{
  @State switch: boolean = true
  build() {
    Column() {
      Button('Hello World')
        .fontSize(50)
        .fontWeight(FontWeight.Bold)
        .onClick(() => {
          this.switch = !this.switch
        })
      if (this.switch) {
        Child({ message: new Message('Child') })
      }
    }
    .height("100%")
    .width('100%')
  }
}

可参考如下自定义组件的生命周期和删除:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/arkts-page-custom-components-lifecycle-V5#%E8%87%AA%E5%AE%9A%E4%B9%89%E7%BB%84%E4%BB%B6%E7%9A%84%E5%88%A0%E9%99%A4

如果if组件的分支改变,或者ForEach循环渲染中数组的个数改变,组件将被删除:

在删除组件之前,将调用其aboutToDisappear生命周期函数,标记着该节点将要被销毁。ArkUI的节点删除机制是:后端节点直接从组件树上摘下,后端节点被销毁,对前端节点解引用,前端节点已经没有引用时,将被JS虚拟机垃圾回收。

自定义组件和它的变量将被删除,如果其有同步的变量,比如@Link、@Prop、@StorageLink,将从同步源上取消注册。

不建议在生命周期aboutToDisappear内使用async await,如果在生命周期的aboutToDisappear使用异步操作(Promise或者回调方法),自定义组件将被保留在Promise的闭包中,直到回调方法被执行完,这个行为阻止了自定义组件的垃圾回收。

以下示例展示了生命周期的调用时机:

// Index.ets
import { router } from '@kit.ArkUI';

@Entry
@Component
struct MyComponent {
  @State showChild: boolean = true;
  @State btnColor: string = "#FF007DFF";

  // 只有被@Entry装饰的组件才可以调用页面的生命周期
  onPageShow() {
    console.info('Index onPageShow');
  }

  // 只有被@Entry装饰的组件才可以调用页面的生命周期
  onPageHide() {
    console.info('Index onPageHide');
  }

  // 只有被@Entry装饰的组件才可以调用页面的生命周期
  onBackPress() {
    console.info('Index onBackPress');
    this.btnColor = "#FFEE0606";
    return true; // 返回true表示页面自己处理返回逻辑,不进行页面路由;返回false表示使用默认的路由返回逻辑,不设置返回值按照false处理
  }

  // 组件生命周期
  aboutToAppear() {
    console.info('MyComponent aboutToAppear');
  }

  // 组件生命周期
  onDidBuild() {
    console.info('MyComponent onDidBuild');
  }

  // 组件生命周期
  aboutToDisappear() {
    console.info('MyComponent aboutToDisappear');
  }

  build() {
    Column() {
      // this.showChild为true,创建Child子组件,执行Child aboutToAppear
      if (this.showChild) {
        Child()
      }
      Button('delete Child')
        .margin(20)
        .backgroundColor(this.btnColor)
        .onClick(() => {
        // 更改this.showChild为false,删除Child子组件,执行Child aboutToDisappear
        this.showChild = false;
      })
      // push到Page页面,执行onPageHide
      Button('push to next page')
        .onClick(() => {
          router.pushUrl({ url: 'pages/Page' });
        })
    }
  }
}

@Component
struct Child {
  @State title: string = 'Hello World';
  // 组件生命周期
  aboutToDisappear() {
    console.info('[lifeCycle] Child aboutToDisappear');
  }

  // 组件生命周期
  onDidBuild() {
    console.info('[lifeCycle] Child onDidBuild');
  }

  // 组件生命周期
  aboutToAppear() {
    console.info('[lifeCycle] Child aboutToAppear');
  }

  build() {
    Text(this.title)
      .fontSize(50)
      .margin(20)
      .onClick(() => {
        this.title = 'Hello ArkUI';
      })
  }
}

// Page.ets
@Entry
@Component
struct Page {
  @State textColor: Color = Color.Black;
  @State num: number = 0;

  // 只有被@Entry装饰的组件才可以调用页面的生命周期
  onPageShow() {
    this.num = 5;
  }

  // 只有被@Entry装饰的组件才可以调用页面的生命周期
  onPageHide() {
    console.log("Page onPageHide");
  }

  // 只有被@Entry装饰的组件才可以调用页面的生命周期
  onBackPress() { // 不设置返回值按照false处理
    this.textColor = Color.Grey;
    this.num = 0;
  }

  // 组件生命周期
  aboutToAppear() {
    this.textColor = Color.Blue;
  }

  build() {
    Column() {
      Text(`num 的值为:${this.num}`)
        .fontSize(30)
        .fontWeight(FontWeight.Bold)
        .fontColor(this.textColor)
        .margin(20)
        .onClick(() => {
          this.num += 5;
        })
    }
    .width('100%')
  }
}

以上示例中,Index页面包含两个自定义组件,一个是被@Entry装饰的MyComponent,也是页面的入口组件,即页面的根节点;一个是Child,是MyComponent的子组件。只有@Entry装饰的节点才可以使页面级别的生命周期方法生效,因此在MyComponent中声明当前Index页面的页面生命周期函数(onPageShow / onPageHide / onBackPress)。MyComponent和其子组件Child分别声明了各自的组件级别生命周期函数(aboutToAppear / onDidBuild/aboutToDisappear)。

  • 应用冷启动的初始化流程为:MyComponent aboutToAppear --> MyComponent build --> MyComponent onDidBuild–> Child aboutToAppear --> Child build --> Child onDidBuild --> Index onPageShow。
  • 点击“delete Child”,if绑定的this.showChild变成false,删除Child组件,会执行Child aboutToDisappear方法。
  • 点击“push to next page”,调用router.pushUrl接口,跳转到另外一个页面,当前Index页面隐藏,执行页面生命周期Index onPageHide。此处调用的是router.pushUrl接口,Index页面被隐藏,并没有销毁,所以只调用onPageHide。跳转到新页面后,执行初始化新页面的生命周期的流程。
  • 如果调用的是router.replaceUrl,则当前Index页面被销毁,上文已经提到,组件的销毁是从组件树上直接摘下子树,所以执行的生命周期流程将变为:新页面的初始化生命周期流程,然后执行Index onPageHide --> MyComponent aboutToDisappear --> Child aboutToDisappear。
  • 点击返回按钮,触发页面生命周期Index onBackPress,且触发返回一个页面后会导致当前Index页面被销毁。
  • 最小化应用或者应用进入后台,触发Index onPageHide。当前Index页面没有被销毁,所以并不会执行组件的aboutToDisappear。应用回到前台,执行Index onPageShow。
  • 退出应用,执行Index onPageHide --> MyComponent aboutToDisappear --> Child aboutToDisappear。
5、HarmonyOS Image如何设置高斯模糊?

参考demo

Text('')
  .width('90%')
  .height('30%')
  .fontSize(20)
  .fontColor(Color.White)
  .textAlign(TextAlign.Center)
  .backdropBlur(50) // 对背景进行模糊
  .backgroundImage($r('app.media.image1'))
  .backgroundImageSize({ width: 400, height: 300 })