news 2026/4/23 9:30:49

鸿蒙中 Web 组件在新窗口打开链接

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
鸿蒙中 Web 组件在新窗口打开链接

本文同步发表于 微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新

当 Web 组件加载的网页(如通过window.open())尝试打开新窗口时,系统并不会自动创建,而是会通知应用层,由开发者决定如何响应该请求(如在弹窗、新页面或新窗口中展示)。这是一个典型的 “通知-响应” 模型。

整个交互流程的角色与步骤如下:

  1. 网页侧:调用window.open()等方法请求新窗口。

  2. ArkWeb 内核:拦截请求,检查name参数对应的 Web 组件是否存在。

  3. 应用侧:通过onWindowNew()回调接收事件,创建新窗口(如CustomDialog)并建立关联。

二、API 与配置

为了启用并管理新窗口行为,需要使用一组特定的属性和回调接口,其作用和关系如下表:

接口/配置所属组件作用与说明关键点
.multiWindowAccess(true)Web 组件属性总开关:允许网页请求打开新窗口。必须设置为true,否则后续流程不会触发。
.allowWindowOpenMethod(true)Web 组件属性脚本开关:允许网页通过window.open()等 JavaScript 方式打开新窗口。通常与multiWindowAccess配合使用。
.onWindowNew(event)Web 组件事件回调核心事件:当网页请求新窗口时触发。开发者需在此回调中创建新窗口并建立关联。回调参数event中的handler是连接新窗口与内核的关键桥梁
event.handler.setWebController(controller)onWindowNew事件参数方法建立关联:将你为新窗口创建的WebviewController实例告知 ArkWeb 内核,使内核能将新网页内容注入该控制器关联的 Web 组件。必须调用,否则渲染进程会阻塞。若无新窗口,参数需设为null
.onActivateContent()Web 组件事件回调激活通知:当网页尝试通过window.open(url, name)打开一个已存在的name窗口时,对应name的 Web 组件会收到此回调,提示应用将其展示到前台(如切换 Tab)。此回调作用于目标窗口对应的 Web 组件,而非发起请求的源组件。

三、示例代码

// 1. 定义新窗口的UI组件(这里使用CustomDialog模拟弹窗窗口) @CustomDialog struct NewWebViewComp { controller?: CustomDialogController; // 为新窗口创建一个独立的控制器 webviewController1: webview.WebviewController = new webview.WebviewController(); build() { Column() { // 新窗口内的Web组件,初始无内容,将由内核注入 Web({ src: "", controller: this.webviewController1 }) .javaScriptAccess(true) .multiWindowAccess(false) // 此新窗口自身不允许再开窗口(根据需要设置) .onWindowExit(() => { /* 窗口关闭处理 */ }) .onActivateContent(() => { // 如果此窗口已被绑定过name,再次被请求打开时会触发这里 console.info("NewWebViewComp onActivateContent") }) } } } @Entry @Component struct WebComponent { // 主窗口的控制器 controller: webview.WebviewController = new webview.WebviewController(); // 用于控制新弹窗 dialogController: CustomDialogController | null = null; build() { Column() { // 2. 主Web组件:加载本地网页,并开启多窗口支持 Web({ src: $rawfile("window.html"), controller: this.controller }) .javaScriptAccess(true) .multiWindowAccess(true) // 总开关:允许打开新窗口 .allowWindowOpenMethod(true) // 允许JS的window.open() // 3. 核心:处理新窗口请求 .onWindowNew((event) => { // 关闭可能已存在的旧弹窗 if (this.dialogController) { this.dialogController.close() } // 为新窗口创建控制器 let popController: webview.Webview.WebviewController = new webview.WebviewController(); // 创建并打开一个自定义弹窗作为“新窗口” this.dialogController = new CustomDialogController({ builder: NewWebViewComp({ webviewController1: popController }), isModal: false // 设置为非模态,防止影响onActivateContent回调 }); this.dialogController.open(); // 4. 关键一步:将新窗口的控制器告知Web内核,建立绑定 event.handler.setWebController(popController); // 如果不调用setWebController或传入null,内核会认为应用未创建新窗口 }) } } }

网页 (window.html) 代码

<!DOCTYPE html> <html> <body> <!-- 点击按钮,触发 window.open() --> <input type="button" value="新窗口中打开网页" onclick="OpenNewWindow()"> <script type="text/javascript"> function OpenNewWindow() { // 打开一个空白页,并写入一些内容 let openedWindow = window.open("about:blank", "", "location=no,status=no,scrollbars=no"); openedWindow.document.write("<p><br><br>打开的窗口</p>"); openedWindow.focus(); } </script> </body> </html>

四、原理

五、注意事项

  1. setWebController必须调用:在onWindowNew回调中,无论是否创建新窗口,都必须调用event.handler.setWebController(...)。如果不调用,会导致 Web 内核的渲染进程阻塞等待

  2. 模态窗口与非模态窗口:使用CustomDialogController时,如果isModal设为true(模态),在某些情况下可能会影响后续onActivateContent等回调的触发。

  3. 内存与生命周期管理

    • 为新窗口创建的WebviewControllerCustomDialogController需要妥善管理(如在onWindowExit回调中关闭和释放),防止内存泄漏。

    • onWindowExit回调中关闭弹窗。

  4. onActivateContent的使用:这个回调是实现类似浏览器“标签页复用”功能的关键。当用户多次点击打开同一个“命名窗口”(name相同)时,可以将已存在的窗口激活并提到前台,而不是重复创建。

  5. OnWindowNewEvent.isUserTrigger参数:在OnWindowNewEvent回调函数中有一个isUserTrigger参数,可用于区分新窗口请求是由用户主动操作(如点击)触发,还是由网页脚本自动触发。有助于更精细的控制。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 3:09:11

《创业之路》-855- 商业模式案例分析 - 中兴通讯

商业模式案例分析&#xff1a;中兴通讯&#xff08;ZTE Corporation&#xff09;中兴通讯&#xff08;ZTE&#xff09;成立于1985年&#xff0c;是中国领先的综合通信技术与解决方案提供商之一&#xff0c;也是全球主要的电信设备制造商和智能终端供应商。作为中国信息通信产业…

作者头像 李华
网站建设 2026/4/17 9:15:09

数据库核心概念深度解析:从基础原理到 SQL 分类

数据库核心概念深度解析&#xff1a;从基础原理到 SQL 分类作为一名技术从业者&#xff0c;无论是网络工程师转型、后端开发入门&#xff0c;还是数据相关岗位学习&#xff0c;数据库都是绕不开的核心技能。本文将系统性拆解数据库的核心概念&#xff0c;涵盖数据库与 DBMS 定义…

作者头像 李华
网站建设 2026/4/18 23:41:06

Hot100——栈

有效的括号给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串 s &#xff0c;判断字符串是否有效。有效字符串需满足&#xff1a;左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。每个右括号都有一个对应的相同类型…

作者头像 李华
网站建设 2026/3/30 12:19:16

Flutter---时间核心类

DateTime - 基础时间类// 创建 DateTime 对象 DateTime now DateTime.now(); // 当前时间 DateTime specific DateTime(2024, 1, 15); // 指定日期 (年,月,日) DateTime detailed DateTime(2024, 1, 15, 10, 30); // 指定日期时间 (年,月,日,时,分…

作者头像 李华
网站建设 2026/4/18 1:12:22

aa---(6)

26.My EasterFocus QuestionWhat does the girl do on Easter?basket Easter(复活节) candy eggs dress familytextMy dress.My hat.My basket.My eggs.My candy.My flowers.My family.My Easter.ConnectionsEaster is a holiday.What are other holidays&#xff1f;Make a l…

作者头像 李华
网站建设 2026/4/17 22:28:26

53、UART 串口通信

UART 串口通信&#xff08;51单片机Modbus协议&#xff09; 一、UART 核心概念与特性 UART&#xff08;Universal Asynchronous Receiver Transmitter&#xff09; 通用异步收发器&#xff0c;是MCU与外部设备异步通信的硬件接口模块&#xff0c;核心特性如下&#xff1a; 异步…

作者头像 李华