鸿蒙6.0应用开发——使用Web组件显示网页弹框

在HTML中,可以使用JavaScript创建三种类型的弹框:警告框window.alert(message)、确认框window.confirm(message)和提示框window.prompt(message, defaultValue)。这些弹框可以用于向用户传递信息、确认操作或请求输入。

当前,ArkWeb暂未提供默认的应用弹框。如果需要网页的弹框能够正常使用,应用需要通过onAlert、onConfirm和onPrompt接口自定义弹框功能。

实现Alert弹框

window.alert()用于显示一个包含可选信息的对话框。警告框用于确保用户可以得到某些信息。当警告框出现后,用户需要点击确定按钮才能继续进行操作。

  • 可选参数message是要显示在警告对话框中的字符串,如果传入其他类型的值,会转换成字符串。
  • 该方法不存在返回值。

应用可以通过onAlert事件监听网页alert方法,并创建合适的弹框。

  • 用AlertDialog创建弹框。

    import { webview } from '@kit.ArkWeb';
    
    @Entry
    @Component
    struct Index {
      @State message: string = 'Hello World';
      webviewController: webview.WebviewController = new webview.WebviewController();
      uiContext: UIContext = this.getUIContext();
    
      build() {
        Row() {
          Web({ src: $rawfile('test.html'), controller: this.webviewController })
            .onAlert((event) => {
              if (event) {
                console.info('event.url:' + event.url);
                console.info('event.message:' + event.message);
                this.uiContext.showAlertDialog({
                  title: 'Warning',
                  message: event.message,
                  confirm:{
                    value: 'confirm',
                    action: () => {
                      console.info('Alert confirmed.');
                      event.result.handleConfirm();
                    }
                  },
                  cancel: () => {
                    event.result.handleCancel();
                  }
                })
              }
              return true;
            })
        }
      }
    }
    

    代码逻辑走读:

    1. 导入模块:代码首先从@kit.ArkWeb导入webview模块,这是用于操作Web视图的API。
    2. 组件定义:使用@Entry@Component装饰器定义了一个名为Index的组件。
    3. 状态初始化:在组件中定义了一个状态变量message,初始值为’Hello World’,以及一个webviewControlleruiContext实例。
    4. 布局构建:在build方法中,使用Row布局开始构建界面。
    5. Web视图加载:在Row布局中嵌入一个Web组件,该组件加载本地HTML文件test.html,并绑定到webviewController
    6. 事件处理:为Web组件设置onAlert事件处理器,当Web视图触发警告框时,捕获事件并执行以下逻辑:
      • 打印警告框的URL和消息。
      • 显示一个AlertDialog,标题为’Warning’,消息内容为Web视图的警告消息。
      • AlertDialog包含确认按钮和取消按钮,分别绑定到确认和取消的事件处理函数。
    7. 事件响应:用户点击确认按钮时,打印’Alert confirmed.'并处理事件结果;用户点击取消按钮时,直接处理事件结果。

    加载的HTML。

    <!-- test.html -->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport"
              content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
        <style>
            button,label,input {
            margin: 5px 0;
            }
        </style>
    </head>
    <body>
    <input type="text" id="alert-message" placeholder="message for alert"><br/>
    <button onclick="handleAlert()">alert</button><br/>
    <script>
        function handleAlert() {
            let message = document.getElementById("alert-message").value;
            let result = window.alert(message ? message : 'alert');
        }
    </script>
    </body>
    </html>
    
  • 用CustomDialog-AlertDialog创建弹框。

    import { AlertDialog } from '@kit.ArkUI';
    import { webview } from '@kit.ArkWeb';
    
    @Entry
    @Component
    struct AlertDialogPage {
      @State message: string = 'Hello World';
      @State title: string = 'Hello World';
      @State subtitle: string = '';
      @State result: JsResult | null = null;
      webviewController: webview.WebviewController = new webview.WebviewController();
      dialogControllerAlert: CustomDialogController = new CustomDialogController({
        builder: AlertDialog({
          primaryTitle: this.title,
          secondaryTitle: this.subtitle,
          content: this.message,
          primaryButton: {
            value: 'confirm',
            role: ButtonRole.ERROR,
            action: () => {
              console.info('Callback when the second button is clicked');
              this.result?.handleConfirm();
            }
          },
        }),
        onWillDismiss: () => {
          this.result?.handleCancel();
          this.dialogControllerAlert.close();
        }
      })
      build() {
        Column() {
          Web({ src: $rawfile('alert.html'), controller: this.webviewController })
            .onAlert((event) => {
              if (event) {
                console.info('event.url:' + event.url);
                console.info('event.message:' + event.message);
                this.title = 'Warning';
                this.message = event.message;
                this.result = event.result;
                this.dialogControllerAlert.open();
              }
              return true;
            })
        }
      }
    }
    

    代码逻辑走读:

    1. 导入模块
      • @kit.ArkUI导入AlertDialog
      • @kit.ArkWeb导入webview
    2. 定义组件
      • 使用@Entry@Component装饰器定义一个名为AlertDialogPage的组件。
    3. 状态变量
      • 定义了四个状态变量:messagetitlesubtitleresult,分别用于存储对话框的内容、标题、副标题、以及对话框的结果。
      • 初始化webviewControllerwebview.WebviewController的一个实例。
      • 初始化dialogControllerAlertCustomDialogController的一个实例,配置了一个AlertDialog对话框,其中包含了对话框的标题、副标题、内容和按钮。
    4. 构建UI
      • 使用Column组件创建一个垂直布局。
      • Column中嵌入一个Web组件,用于加载本地HTML文件alert.html,并设置其控制器为webviewController
      • Web组件添加onAlert事件处理函数,当网页触发警告对话框时,更新状态变量titlemessageresult,并打开自定义的警告对话框。
    5. 事件处理
      • onAlert事件处理函数中,如果事件存在,则打印事件的URL和消息,更新状态变量,并打开自定义的警告对话框。
      • 在对话框的onWillDismiss事件处理函数中,处理取消操作,关闭对话框。

    加载的html。

    <!-- alert.html -->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport"
              content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
        <style>
            button,label,input {
            margin: 5px 0;
            }
        </style>
    </head>
    <body>
    <input type="text" id="alert-message" placeholder="message for alert"><br/>
    <button onclick="handleAlert()">alert</button><br/>
    <script>
        function handleAlert() {
            let message = document.getElementById("alert-message").value;
            let result = window.alert(message ? message : 'alert');
        }
    </script>
    </body>
    </html>
    

    在这里插入图片描述

实现Confirm弹框

window.confirm()用于显示一个包含可选消息的对话框,并等待用户确认或取消该对话框。

  • 可选参数message是要显示在对话框中的字符串,如果传入其他类型的值,会转换成字符串。
  • 该方法返回一个布尔值,表示是否选择了确定(true)或取消(false)。如果应用忽略了页面内的对话框,那么返回值总是false。

确认框用于验证用户是否接受某个操作,常用于询问用户是否离开网页,以防页面表单等数据丢失。

应用可以通过onConfirm事件监听网页confirm方法,并创建合适的弹框。

  • 用AlertDialog创建弹框。

    import { webview } from '@kit.ArkWeb';
    
    @Entry
    @Component
    struct Index {
      @State message: string = 'Hello World';
      webviewController: webview.WebviewController = new webview.WebviewController();
      uiContext: UIContext = this.getUIContext();
    
      build() {
        Column() {
          Web({ src: $rawfile('test.html'), controller: this.webviewController })
            .onConfirm((event) => {
              if (event) {
                console.info('event.url:' + event.url);
                console.info('event.message:' + event.message);
                this.uiContext.showAlertDialog({
                  title: 'Confirm',
                  message: event.message,
                  primaryButton: {
                    value: 'cancel',
                    action: () => {
                      event.result.handleCancel();
                    }
                  },
                  secondaryButton: {
                    value: 'ok',
                    action: () => {
                      event.result.handleConfirm();
                    }
                  },
                  cancel: () => {
                    event.result.handleCancel();
                  }
                })
              }
              return true;
            })
        }
      }
    }
    

    代码逻辑走读:

    1. 导入模块:代码首先从@kit.ArkWeb中导入webview模块,这是用于操作Web视图的工具。
    2. 组件定义:使用@Entry@Component装饰器定义了一个名为Index的组件,表示这是应用的入口组件。
    3. 状态初始化
      • 定义了一个状态变量message,初始值为’Hello World’。
      • 创建了一个webviewController对象,用于控制Web视图的行为。
      • 获取当前UI上下文uiContext,以便在后续操作中使用。
    4. UI构建
      • 使用Column布局组件来组织界面元素。
      • Column中嵌入一个Web组件,指定Web视图的源文件为test.html,并绑定到webviewController
    5. 事件处理
      • Web组件添加onConfirm事件监听器,当Web视图触发确认事件时执行回调函数。
      • 在回调函数中,首先检查事件对象event是否存在。
      • 如果存在,输出事件的URL和消息到控制台。
      • 使用uiContext显示一个确认对话框,对话框标题为’Confirm’,消息内容为event.message
      • 对话框提供了两个按钮:“取消”和“确认”,分别绑定到event.result.handleCancelevent.result.handleConfirm方法。
      • 对话框还定义了一个取消操作,即调用event.result.handleCancel
    6. 返回值:回调函数返回true,表示事件已被处理。

    加载的html。

    <!-- test.html -->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport"
              content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
        <style>
            button,label,input {
            margin: 5px 0;
            }
        </style>
    </head>
    <body>
    result:<label id="confirmLabel" for="confirm"></label><br/>
    <input type="text" id="confirm-message" placeholder="message for confirm"><br/>
    <button id="confirm" onclick="handleConfirm()">confirm</button><br/>
    <script>
        function handleConfirm() {
            let message = document.getElementById("confirm-message").value;
            let result = window.confirm(message ? message : 'confirm');
            console.info(result);
            document.getElementById("confirmLabel").innerHTML=String(result);
        }
    </script>
    </body>
    </html>
    
  • 用CustomDialog-ConfirmDialog创建弹框。

    import { webview } from '@kit.ArkWeb';
    import { ConfirmDialog } from '@kit.ArkUI';
    
    @Entry
    @Component
    struct DialogConfirmDialog {
      @State message: string = 'Hello World';
      @State title: string = 'Hello World';
      @State result: JsResult | null = null;
      webviewController: webview.WebviewController = new webview.WebviewController();
      isChecked = false;
      dialogControllerCheckBox: CustomDialogController = new CustomDialogController({
        builder: ConfirmDialog({
          title: this.title,
          content: this.message,
          // 勾选框选中状态
          isChecked: this.isChecked,
          // 勾选框说明文本
          checkTips: 'No further prompts after prohibition',
          primaryButton: {
            value: 'prohibited',
            action: () => {
              this.result?.handleCancel();
            },
          },
          secondaryButton: {
            value: 'allow',
            action: () => {
              this.isChecked = false;
              console.info('Callback when the second button is clicked');
              this.result?.handleConfirm();
            }
          },
          onCheckedChange: (checked) => {
            this.isChecked = checked;
            console.info('Callback when the checkbox is clicked');
          },
        }),
        onWillDismiss: () => {
          this.result?.handleCancel();
          this.dialogControllerCheckBox.close();
        },
        autoCancel: true
      })
    
      build() {
        Column() {
          Web({ src: $rawfile('confirm.html'), controller: this.webviewController })
            .onConfirm((event) => {
              if (event) {
                if (this.isChecked) {
                  event.result.handleCancel();
                } else {
                  console.info('event.url:' + event.url);
                  console.info('event.message:' + event.message);
                  this.title = 'Confirm';
                  this.message = event.message;
                  this.result = event.result;
                  this.dialogControllerCheckBox.open();
                }
              }
              return true;
            })
        }
      }
    }
    

    代码逻辑走读:

    1. 导入模块:代码首先从@kit.ArkWeb@kit.ArkUI模块中导入webviewConfirmDialog,这是使用ArkUI和ArkWeb功能的前提。
    2. 组件定义:定义了一个名为DialogConfirmDialog的组件,并使用@Entry@Component装饰器标记为入口组件。
    3. 状态变量:初始化了几个状态变量,包括messagetitleresultwebviewControllerisCheckeddialogControllerCheckBox,用于存储对话框内容、结果和Webview控制器等信息。
    4. 对话框控制器:创建了一个CustomDialogController实例dialogControllerCheckBox,用于管理确认对话框的显示和交互。
    5. 对话框配置:在dialogControllerCheckBox中配置了确认对话框,包括标题、内容、按钮文本、勾选框状态和事件处理函数。
    6. Webview配置:在build方法中,配置了一个Webview组件,并设置了其源文件和控制器。Webview组件监听了确认事件,根据用户的选择来决定如何处理事件。
    7. 事件处理:在Webview的确认事件处理函数中,根据用户的选择(是否勾选框被选中)来决定是否取消当前操作或更新对话框内容并打开对话框。

    加载的html。

    <!-- confirm.html -->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport"
              content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
        <style>
            button,label,input {
            margin: 5px 0;
            }
        </style>
    </head>
    <body>
    result:<label id="confirmLabel" for="confirm"></label><br/>
    <input type="text" id="confirm-message" placeholder="message for confirm"><br/>
    <button id="confirm" onclick="handleConfirm()">confirm</button><br/>
    <script>
        function handleConfirm() {
            let message = document.getElementById("confirm-message").value;
            let result = window.confirm(message ? message : 'confirm');
            console.info(result);
            document.getElementById("confirmLabel").innerHTML=String(result);
        }
    </script>
    </body>
    </html>
    

    在这里插入图片描述

实现Prompt弹框

window.prompt()用于显示一个对话框,并等待用户提交文本或取消对话框。用户需要输入某个值,然后点击确认或取消按钮。点击确认返回输入的值,点击取消返回null。

  • 可选参数message向用户显示的一串文本。如果在提示窗口中没有什么可显示的,可以省略。
  • 可选参数defaultValue是一个字符串,包含文本输入字段中显示的默认值。
  • 返回值为用户输入文本的字符串,或null。

提示框用于提示用户输入某个值,常用于需要用户输入临时的口令或验证码等场景。

应用可以通过onPrompt事件监听网页prompt方法,并创建合适的弹框。

  • 用CustomDialog-CustomContentDialog创建弹框。

    import { CustomContentDialog } from '@kit.ArkUI';
    import { webview } from '@kit.ArkWeb';
    
    @Entry
    @Component
    struct PromptDialog {
      @State message: string = 'Hello World';
      @State title: string = 'Hello World';
      @State result: JsResult | null = null;
      promptResult: string = '';
      webviewController: webview.WebviewController = new webview.WebviewController();
      dialogController: CustomDialogController = new CustomDialogController({
        builder: CustomContentDialog({
          primaryTitle: this.title,
          contentBuilder: () => {
            this.buildContent();
          },
          buttons: [
            {
              value: 'cancel',
              buttonStyle: ButtonStyleMode.TEXTUAL,
              action: () => {
                console.info('Callback when the button is clicked');
                this.result?.handleCancel();
              }
            },
            {
              value: 'confirm',
              buttonStyle: ButtonStyleMode.TEXTUAL,
              action: () => {
                this.result?.handlePromptConfirm(this.promptResult);
              }
            }
          ],
        }),
        onWillDismiss: () => {
          this.result?.handleCancel();
          this.dialogController.close();
        }
      });
    
      // 自定义弹出框的内容区
      @Builder
      buildContent(): void {
        Column() {
          Text(this.message)
          TextInput()
            .onChange((value) => {
              this.promptResult = value;
            })
            .defaultFocus(true)
        }
        .width('100%')
      }
    
      build() {
        Column() {
          Web({ src: $rawfile('prompt.html'), controller: this.webviewController })
            .onPrompt((event) => {
              if (event) {
                console.info('event.url:' + event.url);
                console.info('event.message:' + event.message);
                console.info('event.value:' + event.value);
                this.title = 'Prompt';
                this.message = event.message;
                this.promptResult = event.value;
                this.result = event.result;
                this.dialogController.open();
              }
              return true;
            })
        }
      }
    }
    

    代码逻辑走读:

    1. 导入模块
      • @kit.ArkUI导入CustomContentDialog用于创建自定义对话框。
      • @kit.ArkWeb导入webview用于创建Webview组件。
    2. 组件定义
      • 使用@Entry@Component装饰器定义了一个名为PromptDialog的组件。
    3. 状态变量初始化
      • 初始化状态变量messagetitle为’Hello World’,用于对话框的标题和内容。
      • 初始化resultnull,用于存储Webview的提示结果。
      • 初始化promptResult为空字符串,用于存储用户输入的响应内容。
      • 创建webviewControllerdialogController用于控制Webview和对话框的行为。
    4. 对话框配置
      • 使用CustomContentDialog构建对话框,设置主标题、内容构建器和按钮配置。
      • 按钮配置包括取消按钮和确认按钮,分别绑定点击事件处理函数。
      • 当对话框即将消失时,调用handleCancel方法并关闭对话框。
    5. 自定义内容构建
      • 定义buildContent方法,构建对话框的内容区,包括一个文本和一个文本输入框。
      • 文本输入框绑定onChange事件,用于更新promptResult
    6. 组件构建
      • 定义build方法,构建组件的主要结构。
      • 使用Web组件加载本地HTML文件,并绑定onPrompt事件处理函数。
      • 当Webview触发提示事件时,更新对话框的标题、内容和响应结果,并打开对话框。

    加载的html。

    <!-- prompt.html -->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport"
              content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
        <style>
            button,label,input {
            margin: 5px 0;
            }
        </style>
    </head>
    <body>
    result:<label id="promptLabel" for="prompt"></label><br/>
    <input type="text" id="prompt-message" placeholder="message for prompt"><br/>
    <input type="text" id="prompt-value" placeholder="default value for prompt"><br/>
    <button id="prompt" onclick="handlePrompt()">prompt</button><br/>
    <script>
        function handlePrompt() {
            let message = document.getElementById("prompt-message").value;
            let defaultValue = document.getElementById("prompt-value").value;
            let result = window.prompt(message ? message : 'prompt', defaultValue);
            console.info(result);
            document.getElementById("promptLabel").innerHTML=result;
        }
    </script>
    </body>
    </html>
    

需要的资源文件string.json

{
  "string": [
    {
      "name": "from",
      "value": "来自"
    },
    {
      "name": "warn",
      "value": "的警告"
    },
    {
      "name": "notarize",
      "value": "确认"
    },
    {
      "name": "cancel",
      "value": "取消"
    },
    {
      "name": "info",
      "value": "的消息"
    }
  ]
}

在这里插入图片描述

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐