ArkWeb 手记 06|window.open 与页面跳转拦截

前面 01~05,我们搞定生命周期、JS 双向通信、rawfile 静态资源、DevTools 调试、网络请求劫持。

这次要解决 H5 开发里非常高频的痛点:H5 代码调用window.open()打开新页面,在 ArkWeb 里默认没反应;还有 H5 点击链接跳转,想在原生层拦截跳转地址,做权限校验、路由重定向。

我当初踩坑:H5 里写window.open("https://xxx"),网页在浏览器能正常新开标签,放到 ArkWeb 里面点击完全没效果。查文档才知道,ArkWeb 默认不支持自动弹出新窗口,必须通过回调手动接管。

核心误区:window.open不会自动创建新 Web 组件;页面跳转分两种,超链接跳转和 JS 跳转,对应的回调接口不一样,别搞混。

核心概念一句话讲清

  • onNewWindow:专门捕获 H5 调用window.open()新建窗口的请求,在这里手动创建新 ArkWeb 实例加载目标地址。
  • onPageBegin:页面开始跳转的回调,拦截普通 a 标签点击、location.href 这类页面跳转,可以放行或者阻止跳转。

类比:浏览器自带多标签页能力,ArkWeb 默认是单页面容器。H5 想要新开页面,得通知原生,由原生去新建容器承载页面。
前置条件:HarmonyOS7,DevEco Studio,沿用前面工程。

第一步:拦截 window.open,实现 H5 新开页面

复制代码
import { ArkWeb, ArkWebController, WebNewWindowRequest } from '@kit.ArkWeb';

@Entry
@Component
struct WebOpenDemo {
  @State targetUrl: string = "";
  @State showNewWeb: boolean = false;
  controller: ArkWebController = new ArkWebController();
  newWebController: ArkWebController = new ArkWebController();

  aboutToAppear() {
    this.controller.javascriptEnabled = true;
    // 捕获 window.open 新开窗口请求
    this.controller.onNewWindow = (req: WebNewWindowRequest): boolean => {
      // 获取H5想要打开的链接
      this.targetUrl = req.requestUrl;
      // 控制弹窗显示新Web页面
      this.showNewWeb = true;
      // 返回true:代表我们原生接管这个新开窗口动作,ArkWeb不再默认处理
      return true;
    }
  }

  build() {
    Column() {
      // 主ArkWeb页面
      ArkWeb({
        src: $rawfile("index.html"),
        controller: this.controller
      })
      .width('100%')
      .layoutWeight(1)

      // 弹窗,承载window.open打开的新页面
      if(this.showNewWeb){
        Column(){
          Row(){
            Button("关闭新页面")
              .onClick(()=>{
                this.showNewWeb = false;
              })
          }
          ArkWeb({
            src: this.targetUrl,
            controller: this.newWebController
          })
          .width('100%')
          .layoutWeight(1)
        }
        .width('90%')
        .height('80%')
        .border({width:1, color:"#ccc"})
      }
    }
  }
}

配套 H5 index.html 测试代码

复制代码
<button onclick="openNewPage()">点我window.open打开页面</button>
<script>
function openNewPage(){
  window.open("https://www.example.com","_blank")
}
</script>

关键语句拆解:

  1. onNewWindow 返回布尔值,true = 原生接管新开窗口;false = 放弃处理,不打开页面。
  2. 不能直接在回调里面渲染组件,需要用状态变量 @State 控制页面显示。
  3. 新开页面建议单独新建一个 ArkWebController,和主页面控制器隔离,生命周期互不干扰。

第二步:onPageBegin 拦截普通页面跳转(a 标签 /location.href)

如果只想拦截普通页面跳转,不需要新建窗口,用onPageBegin。可以阻止跳转,或者替换跳转地址。

复制代码
aboutToAppear() {
  this.controller.javascriptEnabled = true;
  this.controller.onPageBegin = (url:string): boolean => {
    console.info("准备跳转地址:", url)
    // 拦截指定域名,禁止跳转
    if(url.includes("block-domain.com")){
      console.info("该链接被拦截,禁止访问")
      // 返回true:拦截,不执行跳转
      return true;
    }
    // 返回false:放行,正常跳转
    return false;
  }
}

高频踩坑清单(重点)

  1. ❌ window.open 触发后没有任何响应
    ✅ 没有实现onNewWindow回调,或者回调返回 false,ArkWeb 不会自动创建页面。
  2. ❌ 在 onNewWindow 回调内部直接修改 UI 组件
    ✅ 回调是异步回调,不能直接写 UI 渲染,要用 @State 状态变量驱动页面刷新。
  3. ❌ 新页面复用主页面 ArkWebController
    ✅ 控制器实例复用会导致生命周期混乱,前进后退、缓存互相干扰,新开页面务必新建 controller。
  4. ❌ onPageBegin 只能拦截主页面跳转,iframe 内部跳转不会触发这个回调
    ✅ iframe 内页面跳转,onPageBegin 捕获不到,需要结合 onInterceptRequest 做额外判断。

小扩展:新页面支持前进后退

新的 ArkWebController 自带页面历史栈,可以增加按钮控制页面返回

复制代码
Button("页面后退")
.onClick(()=>{
  if(this.newWebController.canGoBack()){
    this.newWebController.goBack()
  }
})
相关推荐
夜不会漫长6 小时前
C++:内存管理
java·开发语言·c++
徐小黑ACG6 小时前
Golang 基础01
开发语言·后端·golang
可乐鸡翅yeah_6 小时前
HLS 业务 Referer‑Policy 网页元标签引发播放异常排错
前端·javascript·网络·ffmpeg·php·音视频
进击的大海贼6 小时前
基于C#开发的久坐提醒工具
开发语言·c#
平生幻6 小时前
unbuntu虚拟机确认python安装位置
开发语言·python
vipxieliang6 小时前
PHP 依赖注入容器从零实现:控制反转、手动注入与容器管理全解析
后端·php
运维行者_6 小时前
PHP性能监控怎么做?从响应时间到慢函数的6个关键指标
运维·服务器·开发语言·网络·支持向量机·php·接口隔离原则
Wang's Blog6 小时前
Java框架 SpringCloud 快速入门: Nacos 配置管理之添加配置与 dataId 命名规范
java·开发语言·spring cloud
阿俊-全栈开发7 小时前
LikeShop单商户Java商城如何从容承接高并发流量?
java·开发语言·spring boot·spring·系统架构