HarmonyOS Web 组件对话框(Web Dialog)实战:alertconfirmprompt 怎么接?怎么做得像“正常 App”?

HarmonyOS Web 组件对话框(Web Dialog)实战:alert/confirm/prompt 怎么接?怎么做得像“正常 App”?

鸿蒙第四期开发者活动
在 ArkTS 侧把异步逻辑包装成 Promise,Native 侧拿到这个 Promise 对象,然后给它挂 then / catch,在回调里获取异步结果或异常。

本文用一个完整示例,走一遍从 ArkTS 到 Native 的链路。


1. 整体思路

  1. ArkTS 侧:

    • 调用 Native 接口时,把一个 callback 传给 Native。
    • Native 调用这个 callback,ArkTS 在 callback 里 返回一个 Promise 对象
    • Promise 内部用 setTimeout 模拟异步,最终 resolvereject
  2. Native 侧:

    • 通过 napi_call_function 调用 ArkTS 传入的 callback,得到 Promise 对象
    • napi_get_named_property 拿到 Promise 的 then 和 `cat

做 ArkWeb 的同学大概率都遇到过这种瞬间:
你把 H5 接进来了,页面跑得挺好,结果某天产品说:“这里点一下要弹个提示框(alert)/确认框(confirm)/输入框(prompt)。”
你心想:这不就是网页自带的吗?——然后你就发现:ArkWeb 并不会帮你把这些对话框自动弹出来。

官方文档说得很直白:ArkWeb 目前不提供默认网页对话框,如果 Web 页面调用了 alert/confirm/prompt,需要应用侧通过 onAlert/onConfirm/onPrompt 事件自己创建对话框来承接。华为开发者+1

这篇我就按“像人写的、能直接落地”的方式,把你真正需要的东西整理出来:

  • Web 侧:什么时候会触发什么
  • ArkTS 侧:怎么接 onAlert/onConfirm/onPrompt
  • 怎么用 ArkUI 的 Dialog 做出“像 App 一样”的弹窗
  • 最容易踩坑的点(尤其是回调没处理好导致网页卡住)

1)先把底层逻辑搞明白:Web 触发、App 承接

在网页里,这三行大家都很熟:

alert('提示');
confirm('确定删除吗?');
prompt('请输入昵称');

但在 HarmonyOS 的 ArkWeb 里,这些不会自动弹系统弹窗。Web 触发后,控制权会交给应用侧:

  • alert() → 触发 onAlert
  • confirm() → 触发 onConfirm
  • prompt() → 触发 onPrompt 华为开发者+1

你需要在 ArkTS 里监听这些事件并创建弹窗,否则 Web 会“等回调等到怀疑人生”(用户看起来就是点了没反应)。


2)最推荐的实现方式:用 ArkUI 的 Dialog 承接网页弹窗

思路我建议你固定成一句话:

网页只负责发请求(alert/confirm/prompt),App 负责用原生 Dialog 做 UI,并把结果回传给 Web。

因为这样做出来的体验最像“真正的 App”,也方便你统一样式。

顺带一提:ArkWeb 的对话框回调对象/事件在 ArkWeb API 里有明确的接口定义。华为开发者+1


3)一套可复用的模板:onAlert / onConfirm / onPrompt 全接上

下面这段是“工程里最常用”的骨架(你复制后只需要替换 UI 细节):

ArkTS:Web 组件里监听对话框事件

import { webview } from '@kit.ArkWeb';

@Entry
@Component
struct WebDialogDemo {
  private controller: webview.WebviewController = new webview.WebviewController();

  build() {
    Column() {
      Web({ src: $rawfile('web/dialog.html'), controller: this.controller })
        .javaScriptAccess(true)

        // 1) alert:只需要用户点“我知道了”
        .onAlert((event) => {
          // event.message:网页传来的提示文字(不同版本字段名以实际为准)
          // event.result:你需要在用户点击后告诉 Web “已处理”
          AlertDialog.show({
            title: '提示',
            message: event.message ?? '(无内容)',
            confirm: {
              value: '知道了',
              action: () => {
                // 关键:通知 Web 继续执行
                event.result?.confirm?.();
              }
            }
          });
          return true; // 表示由应用侧处理
        })

        // 2) confirm:需要返回 true/false
        .onConfirm((event) => {
          AlertDialog.show({
            title: '确认',
            message: event.message ?? '确定继续?',
            primaryButton: {
              value: '取消',
              action: () => event.result?.cancel?.()
            },
            secondaryButton: {
              value: '确定',
              action: () => event.result?.confirm?.()
            }
          });
          return true;
        })

        // 3) prompt:需要返回输入内容(或取消)
        .onPrompt((event) => {
          // 简化写法:用 TextInput + 自己维护状态
          let inputValue: string = event.defaultValue ?? '';

          AlertDialog.show({
            title: event.message ?? '请输入内容',
            // 这里用自定义内容更舒服(CustomDialog 也可以)
            // 为了示例简洁,用 message + 说明代替
            message: '(示例)这里放一个 TextInput,输入后点击确定回传给 Web',
            primaryButton: {
              value: '取消',
              action: () => event.result?.cancel?.()
            },
            secondaryButton: {
              value: '确定',
              action: () => event.result?.confirm?.(inputValue)
            }
          });
          return true;
        })
    }
    .padding(12)
  }
}

为什么我强调 return true
因为这代表“弹窗由应用侧处理”。官方文档里也明确强调需要通过这些回调自行创建对话框来承接。华为开发者+1

注:不同 API version 下事件对象字段名可能略有差异(例如 message/defaultValue/result 等),但整体机制是一致的:你必须在按钮点击时调用 result 的 confirm/cancel(以及 prompt 的 confirm(text))把结果回传给 Web华为开发者+1


4)Web 侧测试页:三种弹窗一把梭

你放一个最小页面,方便自测:

<!doctype html>
<html>
<body>
  <button onclick="alert('这是 alert 提示')">alert</button>
  <button onclick="console.log(confirm('确定继续吗?'))">confirm</button>
  <button onclick="console.log(prompt('请输入昵称', '程奕红'))">prompt</button>
</body>
</html>

跑起来后你就能直观看到:

  • 点击按钮 → ArkTS 侧弹原生 Dialog
  • 点“确定/取消” → Web 侧拿到返回值

5)几个“特别像人会踩”的坑(提前躲掉)

坑 A:弹窗出来了,但网页像“卡死”

九成是因为你没调用 event.result.confirm() / event.result.cancel()
Web 在等你回信,它当然不会继续执行。

坑 B:prompt 输入框做得很丑/不好用

别硬用 AlertDialog 拼,实际项目里建议用 CustomDialog 做内容区(TextInput、校验提示、字数限制都更自然)。官方也有 ArkTS 自定义对话框(UIContext/CustomDialog)相关指导可参考。华为开发者+1

坑 C:样式不统一

我的建议:你在项目里封一个 WebDialogService

  • alert/confirm/prompt 统一从这里弹
  • UI 样式、按钮文案、埋点、国际化都集中管理
    后期你会感谢自己。

6)一句话收尾

HarmonyOS 的 Web Dialog 不是“网页自己弹”,而是“网页发请求,App 用原生弹窗承接并回传结果”。华为开发者+1
把这套机制吃透,你的 H5 才会真的像“嵌进 App 的业务页面”,而不是一块不受控的网页。

posted @ 2025-12-18 16:28  骑老爷爷过马路  阅读(1)  评论(0)    收藏  举报