☰
ArkWeb手记02|HarmonyOS7 拦截H5跳转与自定义路由接管
2026/10/1 16:11:32 网站建设 项目流程

适配:HarmonyOS7,API26
连载:02/10

开篇:H5跳转不受控,是混合开发第二大坑

做鸿蒙ArkWeb混合应用,写完基础页面加载和生命周期之后,下一个一定会撞上的问题:H5里面点链接,直接在当前Web页面跳转。
想拦截某些链接,跳转到鸿蒙原生页面,或者禁止打开外部网页、拦截弹窗新窗口,默认行为根本做不到。

我之前接手一个项目,H5里面埋了外链。用户一点,直接跳外部网页,回退逻辑混乱;还有H5里window.open()打开新页面,直接失效,要么白屏,要么直接在当前页面覆盖,产品提了一堆bug。

很多新手以为H5的跳转只能交给前端控制。其实不是,HarmonyOS7的ArkWeb提供了跳转拦截回调,我们可以在原生层接管所有URL跳转请求,决定放行、拦截,甚至切到鸿蒙原生页面。

这篇手记,我们就解决路由接管这件事。学会拦截链接、区分内部H5路由和外部链接,处理H5新窗口打开场景,统一混合应用路由逻辑。

本篇目标:

  1. 理解ArkWeb的onUrlIntercept拦截回调触发时机
  2. 区分点击跳转、js跳转、window.open三种不同跳转事件
  3. 编写规则,放行内部业务链接,拦截外部域名
  4. H5 window.open新窗口劫持,用原生页面承载新Web实例
  5. 搭建简易路由管理器,H5链接一键跳转原生ArkUI页面

一、基础概念:ArkWeb跳转拦截到底拦截什么

先分清一件事:H5页面跳转分两类。
一类是用户点击a标签,触发页面跳转;另一类是JS代码执行location.href、window.open触发跳转。
在HarmonyOS7里,所有这类请求,都会经过onUrlIntercept回调。这个回调在页面发起请求之前触发,我们有机会直接决定要不要放行。

一句话类比:onUrlIntercept就像收费站。H5发起跳转请求,先到收费站,由原生代码判断:允许通行就继续加载网页;直接拦下,执行我们自定义逻辑。

常见误区
❌ 拦截回调只拦截a标签点击,JS跳转拦不住
✅ onUrlIntercept可以拦截绝大多数跳转,但是window.open属于单独事件,需要额外监听onNewWindow

HarmonyOS7路由拦截时序:

  1. H5触发跳转(点击链接 / JS修改location.href)
  2. 触发 onUrlIntercept,拿到目标URL
  3. 执行我们写的匹配规则
  4. 返回true:拦截,不再加载这个网页;返回false:放行,ArkWeb正常加载目标页面

划重点:返回值千万别搞反。很多人写反,导致页面点任何链接都被直接拦截,页面卡死。API26文档这点描述很容易看错,踩坑的人特别多。

二、最简代码:实现URL拦截,内外域名区分

先写基础拦截代码,给ArkWeb组件绑定onUrlIntercept。
我们做一个简单规则:本业务域名放行;外部第三方域名直接拦截,弹出提示。

import{Web,WebController,WebResourceError,WebUrlInterceptResult}from'@kit.ArkWeb';@Entry@Componentstruct ArkWebRoutePage{privatewebController:WebController=newWebController();@StatetipMsg:string="";// 业务允许的H5域名白名单privateallowHostList:string[]=["xxx-business.com"];aboutToAppear(){this.webController.setJavaScriptEnabled(true);this.webController.setDomStorageEnabled(true);}build(){Column(){if(this.tipMsg.length>0){Text(this.tipMsg).fontSize(16).fontColor(Color.Orange).margin(12)}Web({src:"https://xxx-business.com/index.html",controller:this.webController}).onUrlIntercept((url:string)=>{console.info("捕获跳转URL:",url);consturlObj=newURL(url);consthost=urlObj.hostname;// 判断是否在白名单constisAllow=this.allowHostList.some(item=>host.includes(item));if(!isAllow){this.tipMsg="外部链接已拦截";// 返回true = 拦截本次跳转returnWebUrlInterceptResult.INTERCEPT;}// 返回false = 放行,正常加载H5页面returnWebUrlInterceptResult.ALLOW;}).width('100%').layoutWeight(1)}}aboutToDisappear(){this.webController.stop();this.webController.destroy();}}

代码逐段解释

  1. onUrlIntercept((url:string)=>{...}):跳转拦截回调,每次跳转都会把目标 URL 丢进来。
  2. new URL (url):解析域名、路径,方便做白名单匹配。注意,非法 URL 会抛出异常,生产环境需要加 try-catch。
  3. WebUrlInterceptResult.INTERCEPT:拦截跳转,不再加载页面;WebUrlInterceptResult.ALLOW:放行。

老版本教程会直接 return true/false,HarmonyOS7 API26 推荐使用枚举常量,可读性更强。

踩坑提醒:如果 H5 页面是本地 rawfile 静态页面,跳转的相对路径也会进入这个拦截回调,写匹配规则的时候要考虑相对路径场景,不要直接报错。

三、进阶场景:H5 window.open 新窗口打开处理

H5 页面经常有window.open("xxx.html"),用来弹出新页面。默认情况下,ArkWeb 不会自动新建页面,这个事件会触发onNewWindow回调。
onUrlIntercept 拦不住 window.open,很多人在这里卡很久。

我们绑定 onNewWindow 回调,当 H5 调用 window.open 的时候,由原生创建新 WebController,打开新的鸿蒙页面。

.onNewWindow((url:string) => { console.info("H5请求打开新窗口,地址:", url); // 这里可以调用路由,打开新页面,传入目标url // router.pushUrl打开新的ArkUI页面,新页面里面挂载独立Web组件 return true; })

返回 true 代表我们原生接管新窗口;返回 false,代表不支持新窗口,H5 的 window.open 直接失效。

这里要注意:每一个新窗口,都需要独立的 WebController 实例。不要复用当前页面的 controller,复用会导致两个页面互相抢占内核,出现渲染错乱。

四、混合路由:H5 链接直接跳转鸿蒙原生页面

这是混合开发非常实用的能力。约定一套自定义协议,比如harmony://native/pageDetail。
H5 点击链接,触发 onUrlIntercept,识别这个自定义协议,直接拦截,调用鸿蒙原生路由,打开原生页面,不加载任何网页。

修改拦截回调内部逻辑:

.onUrlIntercept((url:string)=>{console.info("捕获跳转URL:",url);// 匹配自定义原生协议if(url.startsWith("harmony://native/")){// 拦截,打开原生页面router.pushUrl({url:url});returnWebUrlInterceptResult.INTERCEPT;}consturlObj=newURL(url);consthost=urlObj.hostname;constisAllow=this.allowHostList.some(item=>host.includes(item));if(!isAllow){this.tipMsg="外部链接已拦截";returnWebUrlInterceptResult.INTERCEPT;}returnWebUrlInterceptResult.ALLOW;})

注意:需要导入 router 模块import router from '@ohos.router';
这种方案可以做到 H5 和原生路由统一管理。H5 不用关心原生页面怎么实现,只需要跳转约定协议链接。

五、异常兜底:URL 解析容错,防止页面崩溃

如果 H5 传了畸形、非法 URL,new URL(url)会直接抛出异常,整个页面直接崩溃。生产环境必须包一层 try catch。

.onUrlIntercept((url:string)=>{try{console.info("捕获跳转URL:",url);if(url.startsWith("harmony://native/")){router.pushUrl({url:url});returnWebUrlInterceptResult.INTERCEPT;}consturlObj=newURL(url);consthost=urlObj.hostname;constisAllow=this.allowHostList.some(item=>host.includes(item));if(!isAllow){this.tipMsg="外部链接已拦截";returnWebUrlInterceptResult.INTERCEPT;}returnWebUrlInterceptResult.ALLOW;}catch(err){console.error("URL解析失败",err);returnWebUrlInterceptResult.INTERCEPT;}})

六、真机调试,路由日志查看

模拟器测试跳转拦截逻辑,最好打开日志窗口。每次跳转,url 都会打印到控制台。
测试流程:

  1. H5 页面添加 a 标签,分别写内部业务链接、外部链接、自定义 native 协议链接
  2. 逐个点击,观察日志
  3. 检查:内部链接正常打开;外部链接拦截;native 协议跳转原生页面

小坑:部分 H5 框架路由是前端 hash 路由,# 后面的内容不会触发页面刷新,onUrlIntercept 不会触发。hash 路由属于前端内部状态变更,不会发起页面跳转请求,这点一定要分清。

七、本篇总结 + 课后练习任务

知识点汇总

  1. onUrlIntercept 在跳转发起前拦截请求,可以放行或者阻断网页加载;返回枚举不要写反。
  2. window.open 不会触发 onUrlIntercept,需要单独监听 onNewWindow 回调,新建独立 Web 实例。
  3. 自定义协议可以打通 H5 到原生页面跳转,实现混合应用路由统一。
  4. URL 解析一定要增加 try-catch,畸形 URL 会直接造成页面崩溃。
  5. hash 模式前端路由不会触发页面跳转拦截,这是前端路由本身的特性。

实践任务,为下一期做铺垫

基于本篇代码自行实现两点:

  1. 增加拦截黑名单域名列表,匹配关键词直接阻断;
  2. 监听页面回退事件,控制 Web 页面的 goBack 逻辑,和鸿蒙系统返回按键联动。

下一期手记 03,我们讲 ArkWeb 返回按键、历史栈管理,处理 H5 页面回退与原生页面回退冲突问题。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询