/**
* 嵌入模式 Web 控制器,供 `TencentQianWebViewComponent` 使用。
*
* 嵌入模式(Component)把顶栏 / 底栏等 UI 完全交给宿主自绘,但 ArkUI 中父组件无法直接
* 调用子组件的命令式方法。宿主通过创建本控制器并作为 `controller` 入参传给
* `TencentQianWebViewComponent`,即可在自绘的返回按钮 / 重试按钮里主动操控内部 WebView
* (历史后退、重新加载等)。对齐 ArkUI 官方 `WebviewController` / `TextAreaController` 的
* 控制器对象模式。
*
* **生命周期**:组件 `aboutToAppear` 时把内部命令注入本控制器(`attachInternal`),
* `aboutToDisappear` 时复位为 no-op(`detachInternal`)——组件销毁后宿主的误调用安全无副作用。
*
* **典型用法**:
* ```ts
* private webController = new TencentQianWebViewController();
*
* // 自绘顶栏返回按钮 / onBackPress
* Text('<').onClick(() => {
* if (!this.webController.handleBack()) {
* router.back(); // H5 已在首屏,才真正退出
* }
* });
*
* TencentQianWebViewComponent({
* url: this.url,
* context: this.context,
* controller: this.webController,
* onSignResult: this.handleSignResult
* });
* ```
*/
export class TencentQianWebViewController {
// —— 内部命令(组件 attach 时注入,detach 时复位为 no-op)——
private _canGoBack: () => boolean = (): boolean => false;
private _goBack: () => void = (): void => {
// no-op until attached
};
private _reload: () => void = (): void => {
// no-op until attached
};
/**
* 内部 WebView 是否可在 H5 历史栈内后退。
*
* 实时查询 `accessBackward()`,可覆盖整页导航与 SPA(`pushState`/`hashchange`)软路由两种
* 历史深度,比 `OnTitleChanged` 回调里的整页快照更准确。组件未挂载时返回 false。
*/
canGoBack(): boolean {
return this._canGoBack();
}
/** 在 H5 历史栈内后退一级。已在首屏(不可后退)时为 no-op。 */
goBack(): void {
this._goBack();
}
/** 重新加载当前页。配合 `OnRenderUnrecoverable` 可实现「重试」按钮。 */
reload(): void {
this._reload();
}
/**
* 组合返回处理。可后退则退一级并返回 `true`(已消费);否则返回 `false`
* (宿主应自行关闭页面,如 `router.back()`)。语义与内置 Page 模式的返回处理一致。
*
* 宿主自绘顶栏返回按钮 / `onBackPress` 直接转发本方法即可。
*/
handleBack(): boolean {
if (this.canGoBack()) {
this.goBack();
return true;
}
return false;
}
// ─────────────── 以下为 internal,仅供 TencentQianWebViewComponent 调用 ───────────────
/** 【internal】组件挂载时注入内部命令,请勿由业务方调用。 */
attachInternal(canGoBack: () => boolean, goBack: () => void, reload: () => void): void {
this._canGoBack = canGoBack;
this._goBack = goBack;
this._reload = reload;
}
/** 【internal】组件销毁时复位为 no-op,防止野引用,请勿由业务方调用。 */
detachInternal(): void {
this._canGoBack = (): boolean => false;
this._goBack = (): void => {
// no-op
};
this._reload = (): void => {
// no-op
};
}
}
|