【鸿蒙应用ArkTS开发系列】- Har包中子组件中监听生命周期实现

文章目录

  • 前言
  • 解决思路
    • 1. 集成方定义壳页面
    • 2. 生命函数钩子函数
      • 1. 壳页面调用生命周期函数
      • 2. 子组件进行生命周期函数处理方法注入
  • 总结

前言

在鸿蒙应用开发中,有时候我们会创建HAR 模块封装一些SDK能力提供给第三方APP进行集成。
鸿蒙的har 包并不支持定义page页面对外导出,也不支持配置路由信息,因此我们多是在har包中提供组件,通过导出组件的形式,提供给App引用使用。
在鸿蒙中,非@Entry装饰的组件,只能收到如下生命周期函数的回调

  • aboutToAppear?(): void;
  • aboutToDisappear?(): void;

对于页面级组件来说,就可以收到

  • onPageShow?(): void;
  • onPageHide?(): void;
  • onBackPress?(): void;

但是在实际使用过程中,如果我们的har包中想提供跟页面组件一样的功能,受限于har限制,不能定义为@Entry 组件,因而无法接收到上述三个函数的回调,实际功能会收到限制。那有没有办法解决上述问题呢?

解决思路

1. 集成方定义壳页面

我们在har模块中定义一个子组件,pages/SdkPage.ets

@Component
export struct SdkPage {

build() {
...
}

}

在App中定义壳页面,pages/SdkPageShell.ets
这里也可以创建一个HSP对外提供,壳页面配置在HSP包中,对外提供HSP给App集成(这个HSP的,后面有时间在单独写一篇进行讲解SDK的封装,有兴趣的可以私信我或者评论区留言)。

@Entry
@Component
export struct SdkPageShell {

  build() {
    Column() {
      SdkPage()
    }.width('100%')
    .height('100%')
  }
}

套娃模式,这样我们就能将har包中的子组件作为页面级别进行展示了。App需要对SdkPageShell进行页面路由配置。
SdkPageShell 作为一个空壳页面。
但是在实际开发中,就会出现正文前言提到的问题,有部分生命周期函数无法收到回调, 导致我们开发页面功能时处处受限,比如页面隐藏时进行一些消息取消订阅,页面显示时进行消息订阅,如果是要做编辑功能,希望是用户在触发手机实体键的时候,弹窗询问用户是否进行数据保存,不能收到
onBackPress回调,那功能就无法实现了。
那应该怎么做呢,接着往下看。

2. 生命函数钩子函数

经过对子组件的个追踪,发现 在子组件中,是能够获取到父组件的实例的parent_,那我们就可以对其进行一点点的处理。如果我们的子组件是页面组件下的一级子组件,那this[‘parent_’] 拿到的就是上文提到的壳页面SdkPageShell ,
parent_无法直接获取到,我们通过this[‘parent_’] 就可以拿到实例。
那这里有一个思路,我们对this[‘parent_’] 进行一个生命周期函数的方法注入。

在SdkPage.ets中,

 
 aboutToAppear() {
    this['parent_'].onBackPress= this.onBackPress.bind(this);
  };
  onBackPress() {
    Logger.info(this.TAG, 'onBackPress is called');
    return true;
  }

既然按实体返回键的时候,系统会回调壳页面的onBackPress函数,在壳页面中重写onBackPress就可以收到回调, 那我们这里给壳页面注入一个onBackPress进行替换,然后绑定到SdkPage子组件上的onBackPress中去,这样是不是就可以收到回调呢?按这个思路好像是行得通,那就运行试试看,可是很遗憾不能生效。原因是我们改动的是运行期壳页面的onBackPress方法,系统触发实际调用的是CustomComponent的onBackPress。
那壳页面重写onBackPress是能够收到回调,那在壳页面进行一点修改不就可以了,

1. 壳页面调用生命周期函数

在SdkPageShell.ets中,

@Entry
@Component
export struct SdkPageShell {

  build() {
    Column() {
      SdkPage()
    }.width('100%')
    .height('100%')
  }

  onBackPress() {
    if (this['onBackPressHook']) {
      return this['onBackPressHook'].call(this);
    }
  }
}
  1. 重写onBackPress方法
  2. 判断是否有onBackPressHook方法,如果有,触发onBackPressHook,根据onBackPressHook返回值确认是否拦截返回
  3. 如果没有定义onBackPressHook,就直接不处理

看到这里,会不会有点懵,onBackPressHook是啥,SdkPageShell中并未定义onBackPressHook,这里的代码能生效吗,相信有的同学已经反应过来,没错,我们要到子组件中对SdkPageShell进行 onBackPressHook方法的注入。

2. 子组件进行生命周期函数处理方法注入

这里贴下完整代码:

在SdkPage.ets中,

@Component
export struct SdkPage {

	build() {
	...
	}

	aboutToAppear() {
    	this.addEvent();
  	};

  	aboutToDisappear() {
  	}

 	addEvent() {
    	this['parent_'].onBackPressHook= this.onBackPress.bind(this);
  	}

  	onBackPress() {
    	Logger.info(this.TAG, 'onBackPress is called');
    	this.handlePageBack();
    	return true;
  	}
}

这样,在按了手机的物理返回键的时候,子组件SdkPage 就能在onBackPress中收到回调,在handlePageBack中进行返回事件处理,比如弹窗提供用户进行数据保存, return true意思是要拦截系统返回,这样页面就不会被关闭。

总结

其他的生命周期函数,处理方式跟上述的方式一致,总结思路如下:

  1. 壳页面在触发生命周期函数回调时,调用生命周期函数处理函数(需判断是否有定义)
  2. 子组件给壳页面注入生命周期函数处理函数,绑定到自身的方法中。

上述方法,只需要App配合,写少量代码,在壳页面中进行生命周期函数的调用,或者是SDK提供方提供壳页面给到App。如果觉得这样还是不够简洁,那就得考虑提供HSP包给App集成,而不是提供HAR包,这样就可以直接提供Page而不是提供组件。 上面方案也只是一个实现的思路之一,也是有其局限性,比如多个子组件的情况下,就会存在多注入覆盖的问题,因此需要根据实际开发情况来选择实现方案,本文这里仅提供一种实现思路,如果有其他实现方式,欢迎评论区探讨。谢谢阅读!

你可能感兴趣的:(Harmony,harmonyos,ArkUI,ArkTS,鸿蒙开发)