当前位置: 首页 > article >正文

【鸿蒙HarmonyOS Next实战开发】Web组件H5界面与原生交互-抽奖页面

想必很多人都经历过这样的情况:当我们点击某个应用的页面时,往往会跳转到一个类似于浏览器加载的页面,只有等到加载完成之后,才会呈现出该页面的具体内容。通常情况下,加载和显示网页的任务都是由浏览器来完成的。
而ArkUI为我们提供了Web组件,借助这一组件,我们就可以在自己的应用程序中轻松嵌入一个“浏览器”,从而便捷地展示各种各样的网页内容。

图1 web组件示例图

本文将为您介绍Web组件一些常用API的使用。

Web组件介绍

本文将为您介绍Web组件的一些常用API的使用方法。

Web组件是一种具备网页显示能力的组件。它依赖两个关键参数:src资源地址和controller控制器。其中,src资源地址既支持本地资源,也支持网络资源;controller控制器由@ohos.web.webview提供,用于控制Web组件的各种行为。

表1 Web组件参数介绍

参数名

参数类型

必填

参数描述

src

ResourceStr

网页资源地址。如果访问本地资源文件,使用$rawfile或者resource协议。如果加载应用包外沙箱路径的本地资源文件,使用file://沙箱文件路径。

controller

WebviewController

控制器。可以控制Web组件的各种行为,如网页前进、后退等

通过$rawfile加载本地资源

对于src参数,如果需要加载本地网页,可以通过$rawfile加载本地资源文件。

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

@Entry
@Component
struct WebComponent {
  controller: webview.WebviewController = new webview.WebviewController()
  build() {
    Column() {
      // 通过$rawfile加载本地资源文件。
      Web({ src: $rawfile("index.html"), controller: this.controller })
    }
  }
}

通过resource协议加载本地资源文件

对于src参数,如果需要加载本地网页,也可以通过resource协议加载本地资源文件。

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

@Entry
@Component
struct WebComponent {
  controller: webview.WebviewController = new webview.WebviewController()
  build() {
    Column() {
      // 通过resource协议加载本地资源文件。
      Web({ src: "resource://rawfile/index.html", controller: this.controller })
    }
  }
}

加载在线网页

对于src参数,如果需要加载在线网页,可以直接传入对应的网页地址。


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

@Entry
@Component
struct WebComponent {
controller: webview.WebviewController = new webview.WebviewController()
build() {
Column() {
Web({ src: 'www.example.com', controller: this.controller })
}
}
}

    如果需要访问在线网页,需要在module.json5文件中添加网络权限:ohos.permission.INTERNET。

    "module": {
    "requestPermissions": [
    {"name": "ohos.permission.INTERNET"}
    ]
    }

    Webview的基本使用

    @ohos.web.webview是系统提供的基础能力,提供了许多web控制的能力。例如,WebMessagePort、 WebviewController等。

    表2 Webview能力介绍

    名称

    说明

    WebMessagePort

    通过WebMessagePort可以进行消息的发送以及接收。

    WebviewController

    通过WebviewController可以控制Web组件各种行为。

    WebCookieManager

    通过WebCookie可以控制Web组件中的cookie的各种行为

    WebviewController

    通过WebviewController可以控制Web组件各种行为。一个WebviewController对象只能控制一个Web组件,且必须在Web组件和WebviewController绑定后,才能调用WebviewController上的方法(静态方法除外)。

    WebviewController下包含runJavaScript、 registerJavaScriptProxy、 createWebMessagePorts等接口。

    表3 WebviewController接口介绍

    接口名称

    说明

    runJavaScript

    异步执行JavaScript脚本,并通过回调方式返回脚本执行的结果。runJavaScript需要在loadUrl完成后,比如onPageEnd中调用。

    registerJavaScriptProxy

    注入JavaScript对象到window对象中,并在window对象中调用该对象的方法。

    createWebMessagePorts

    创建Web消息端口

    ArkTS调用H5

    runJavaScript(script: string): Promise<string>

    异步执行JavaScript脚本,并通过Promise方式返回脚本执行的结果。runJavaScript需要在loadUrl完成后,比如onPageEnd中调用。

    import { webview } from '@kit.ArkWeb';
    import { BusinessError } from '@kit.BasicServicesKit';
    
    @Entry
    @Component
    struct WebComponent {
      controller: webview.WebviewController = new webview.WebviewController();
    
      build() {
        Column() {
          Web({ src: $rawfile('index.html'), controller: this.controller })
            .javaScriptAccess(true)
            .onPageEnd(e => {
              try {
                this.controller.runJavaScript('test()')
                  .then((result) => {
                    console.log('result: ' + result);
                  })
                  .catch((error: BusinessError) => {
                    console.error("error: " + error);
                  })
                if (e) {
                  console.info('url: ', e.url);
                }
              } catch (error) {
                let e: BusinessError = error as BusinessError;
                console.error(`ErrorCode: ${e.code},  Message: ${e.message}`);
              }
            })
        }
      }
    }

    加载html文件

    <!-- index.html -->
    <!DOCTYPE html>
    <html>
    <meta charset="utf-8">
    <body>
    Hello world!
    </body>
    <script type="text/javascript">
    function test() {
    console.log('Ark WebComponent')
    return "This value is from index.html"
    }
    </script>
    </html>

    案例介绍

    在这个案例中抽奖转盘是一个Web页面。我们点击抽奖,Web页面中的抽奖转盘会开始运动,(停顿)结束抽奖后,原生页面会弹出一个提示弹窗。

    图2 抽奖转盘案例

    Web页面准备

    Web抽奖应用的本地页面代码在entry\src\main\resources目录下,由index.html、index.js、index.css文件组成。抽奖方法的入口函数为startDraw,定义在index.js文件中,为Web应用。

    index.html文件代码如下所示:

    
    <!DOCTYPE html>
    <html>
    <head>
    <link rel="stylesheet" type="text/css" href="./css/index.css">
    <meta charset="UTF-8">
    <title>抽奖页面</title>
    <style>
    #prize {
    border-radius: 16px 16px 16px 16px;
    background-image: linear-gradient(180deg, #A2DAFF 0%, #EAF5FF 100%);
    margin-left: 1.82%;
    margin-top: 1.43%;
    width: 96.5%;
    height: 96.7%;
    }
    </style>
    </head>
    <body>
    <div class="luckyDraw">
    <!-- Use an unordered list to implement a lottery tray -->
    <ul id="prize" class="prizes">
    <li class="prizes-li active"><img class="pic" src="#"></li>
    <li class="prizes-li"><img class="pic" src="#"></li>
    <li class="prizes-li"><img class="pic" src="#"></li>
    <li class="prizes-li"><img class="pic" src="#"></li>
    <li class="prizes-li"><img class="pic" src="#"></li>
    <li class="prizes-li"><img class="pic" src="#"></li>
    <li class="prizes-li"><img class="pic" src="#"></li>
    <li class="prizes-li"><img class="pic" src="#"></li>
    <li class="prizes-li"><img class="pic" onclick="startDraw()" src="#"></li>
    </ul>
    </div>
    <script src="./js/index.js"></script>
    </body>
    </html>

      index.js关键代码如下所示:

      
      // 奖品数组
      let prizesArr = ["啤酒", "奶茶", "汉堡", "咖啡", "西瓜", "鸡腿", "柠檬", "蛋糕"];
      // 奖品对应的图片数组
      let arrBigImg = ["./img/1-beer.png", "./img/2-milk.png", "./img/3-hamburg.png",
      "./img/4-coffee.png", "./img/5-watermelon.png", "./img/6-drumstick.png",
      "./img/7-lemon.png", "./img/8-cake.png", "./img/9-prizes.png"];
      // 省略其他的其他参数
      ...
      // 转盘函数
      function roll() {
      // 省略实现代码
      ...
      }
      
      function startDraw() {
      if (isClick) {
      count = 0;
      // 随即生成位置
      index = Math.floor(Math.random() * prizesArr.length + 1);
      roll();
      isClick = false;
      }
      }
      
      function openDialog() {
      confirm(prizesArr[prizesPosition]);
      }

        原生页面

        为了实现抽奖功能,在原生页面需要实现的具体步骤如下所示:

        1. 在按钮的点击事件中,通过runJavaScript方法,来调用Web页面中的抽奖方法。
        2. Web页面完成抽奖后,我们要在Web页面中调用confirm方法,提示抽奖完成。
        3. 完成抽奖后,要在原生页面中写一个onConfirm的确认事件。
        4. 在onConfirm确认事件中,调用AlertDialog方法,来实现二次确认弹窗, 用于用户的友好交互。

        ArkTS关键代码如下所示:

        
        import { webview } from '@kit.ArkWeb';
        import { router } from '@kit.ArkUI';
        
        @Entry
        @Component
        struct WebPage {
        // 创建WebviewController对象
        webController: webview.WebviewController = new webview.WebviewController();
        build() {
        Stack({ alignContent: Alignment.TopStart }) {
        ...
        Row() {
        Column() {
        Row() {
        ...
        // Web组件,src为资源地址,controller为控制器
        Web({ src: this.params['path'], controller: this.webController })
        .zoomAccess(false)
        .width(Const.WebConstant_WIDTH)
        .aspectRatio(1)
        // 网页调用confirm()告警时触发此回调
        .onConfirm((event) => {
        // 用户定义的弹窗
        AlertDialog.show({
        message: Const.WEB_ALERT_DIALOG_TEXT_VALUE + event?.message,
        confirm: {
        value: $r('app.string.web_alert_dialog_button_value'),
        action: () => {
        event?.result.handleConfirm();
        }
        },
        cancel: () => {
        event?.result.handleCancel();
        }
        });
        return true;
        })
        ...
        // 抽奖按钮
        Button($r('app.string.btnValue'))
        .fontSize(Const.WebConstant_BUTTON_FONT_SIZE)
        .fontColor($r('app.color.start_window_background'))
        .margin({ top: Const.WebConstant_BUTTON_MARGIN_TOP })
        .width(Const.WebConstant_BUTTON_WIDTH)
        .height(Const.WebConstant_BUTTON_HEIGHT)
        .backgroundColor($r('app.color.blue'))
        .borderRadius(Const.WebConstant_BUTTON_BORDER_RADIUS)
        .onClick(() => {
        // 调用js函数的入口
        this.webController.runJavaScript('startDraw()');
        })
        }
        .width(Const.WebConstant_FULL_WIDTH)
        .height(Const.WebConstant_FULL_HEIGHT)
        }
        ...
        }
        }

          http://www.kler.cn/a/532924.html

          相关文章:

        1. 计算机网络——三种交换技术
        2. Linux第105步_基于SiI9022A芯片的RGB转HDMI实验
        3. 【算法】经典博弈论问题——威佐夫博弈 python
        4. 寻迹传感器模块使用说明
        5. 多线程的常用方法
        6. 【大数据技术】教程05:本机DataGrip远程连接虚拟机MySQL/Hive
        7. Fastdds学习分享_xtpes_发布订阅模式及rpc模式
        8. unity报错不存在类型或者命名空间
        9. Java集合概述(Ⅱ)
        10. 企业资金管理-司库(Treasury)
        11. RESTful API的设计原则与这些原则在Java中的应用
        12. MQTT实战之在vue和java中使用
        13. 编程语言中制表符的打印和输出@C#为例进行说明
        14. 人类心智逆向工程:AGI的认知科学基础
        15. 04树 + 堆 + 优先队列 + 图(D1_树(D15_哈夫曼树/霍夫曼树))
        16. 算法与数据结构(合并有序链表)
        17. Vue.js 如何选择合适的组件库
        18. Spring PropertyPlaceholderConfigurer多配置问题
        19. Verilog基础(三):过程
        20. INA226的初次使用
        21. Java基础学习笔记-标识符、变量、常量、关键字
        22. 【C++】Lambda表达式
        23. Linux 文件和目录
        24. 图像增广:用OpenCV实现的6个自动图像增强策略
        25. 【数据分析】豆瓣电影Top250的数据分析与Web网页可视化(numpy+pandas+matplotlib+flask)
        26. UE求职Demo开发日志#19 给物品找图标,实现装备增加属性,背包栏UI显示装备