鸿蒙ArkTS页面如何与H5页面交互?

news/2025/2/25 9:10:23

鸿蒙页面如何与H5页面交互

    • 先看效果
    • 前言
    • 通信功能介绍
    • Web组件使用问题
  • Harmony OS NEXT版本(接口及解决方案兼容API12版本或以上版本)

先看效果

在这里插入图片描述
功能介绍

  • 点击Click Me按钮可以接收展示鸿蒙传递给html的内容
  • 点击霓虹灯按钮可以同步更新底部鸿蒙页面的按钮内容“打开”或“关闭”
  • 点击底部鸿蒙页面的按钮,可以同步修改html的霓虹灯按钮状态

前言

在开发App时,我们经常会遇到使用webView加载H5页面的场景,这样做的好处就不多加赘述了,那么鸿蒙App如何加载H5页面呢?又怎么与H5页面进行通信呢?,废话少说,直接上代码。

通信功能介绍

App可以通过runJavaScript()方法调用html页面的JavaScript相关函数。 在下面的示例中,点击App的“runJavaScript”按钮时,来触发html页面的change()方法更新霓虹灯按钮状态。

html通过鸿蒙的test方法,获取鸿蒙传递过来的数据。通过出发changeBtnText同步更新鸿蒙按钮的内容。

html文件目录:harmonyApp\entry\src\main\resources\rawfile
html代码如下:

<!-- index.html -->
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>霓虹灯按钮拨动特效</title>
    <style>
        * {
            border: 0;
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }

        :root {
            --hue: 223;
            --off-hue: 3;
            --on-hue1: 123;
            --on-hue2: 168;
            --fg: hsl(var(--hue), 10%, 90%);
            --primary: hsl(var(--hue), 90%, 50%);
            --trans-dur: 0.6s;
            --trans-timing: cubic-bezier(0.65, 0, 0.35, 1);
            font-size: calc(40px + (60 - 40) * (100vw - 320px) / (2560 - 320));
        }

        body,
        input {
            font: 1em/1.5 sans-serif;
        }

        body {
            background-image: linear-gradient(45deg, hsl(var(--hue), 10%, 20%), hsl(var(--hue), 10%, 10%));
            color: var(--fg);
            display: flex;
            height: 100vh;
            transition: background-color var(--trans-dur), color var(--trans-dur);
        }

        .common{
            height: 6em;
            width: 5em;
        }

        .switch,
        .switch__input {
            -webkit-tap-highlight-color: #0000;
        }

        .switch {
            display: block;
            margin: auto;
            position: relative;
            width: 5em;
            height: 3em;
        }

        .switch__base-outer,
        .switch__base-inner {
            display: block;
            position: absolute;
        }

        .switch__base-outer {
            border-radius: 1.25em;
            box-shadow: -0.125em -0.125em 0.25em hsl(var(--hue), 10%, 30%), 0.125em 0.125em 0.125em hsl(var(--hue), 10%, 30%) inset, 0.125em 0.125em 0.25em hsl(0, 0%, 0%), -0.125em -0.125em 0.125em hsl(var(--hue), 10%, 5%) inset;
            top: 0.125em;
            left: 0.125em;
            width: 4.75em;
            height: 2.75em;
        }

        .switch__base-inner {
            border-radius: 1.125em;
            box-shadow: -0.25em -0.25em 0.25em hsl(var(--hue), 10%, 30%) inset, 0.0625em 0.0625em 0.125em hsla(var(--hue), 10%, 30%), 0.125em 0.25em 0.25em hsl(var(--hue), 10%, 5%) inset, -0.0625em -0.0625em 0.125em hsla(var(--hue), 10%, 5%);
            top: 0.375em;
            left: 0.375em;
            width: 4.25em;
            height: 2.25em;
        }

        .switch__base-neon {
            display: block;
            overflow: visible;
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: auto;
        }

        .switch__base-neon path {
            stroke-dasharray: 0 104.26 0;
            transition: stroke-dasharray var(--trans-dur) var(--trans-timing);
        }

        .switch__input {
            outline: transparent;
            position: relative;
            width: 100%;
            height: 100%;
            -webkit-appearance: none;
            appearance: none;
        }

        .switch__input:before {
            border-radius: 0.125em;
            box-shadow: 0 0 0 0.125em hsla(var(--hue), 90%, 50%, 0);
            content: "";
            display: block;
            position: absolute;
            inset: -0.125em;
            transition: box-shadow 0.15s linear;
        }

        .switch__input:focus-visible:before {
            box-shadow: 0 0 0 0.125em var(--primary);
        }

        .switch__knob,
        .switch__knob-container {
            border-radius: 1em;
            display: block;
            position: absolute;
        }

        .switch__knob {
            background-color: hsl(var(--hue), 10%, 15%);
            background-image: radial-gradient(88% 88% at 50% 50%, hsl(var(--hue), 10%, 20%) 47%, hsla(var(--hue), 10%, 20%, 0) 50%), radial-gradient(88% 88% at 47% 47%, hsl(var(--hue), 10%, 85%) 45%, hsla(var(--hue), 10%, 85%, 0) 50%), radial-gradient(65% 70% at 40% 60%, hsl(var(--hue), 10%, 20%) 46%, hsla(var(--hue), 10%, 20%, 0) 50%);
            box-shadow: -0.0625em -0.0625em 0.0625em hsl(var(--hue), 10%, 15%) inset, -0.125em -0.125em 0.0625em hsl(var(--hue), 10%, 5%) inset, 0.75em 0.25em 0.125em hsla(0, 0%, 0%, 0.8);
            width: 2em;
            height: 2em;
            transition: transform var(--trans-dur) var(--trans-timing);
        }

        .switch__knob-container {
            overflow: hidden;
            top: 0.5em;
            left: 0.5em;
            width: 4em;
            height: 2em;
        }

        .switch__knob-neon {
            display: block;
            width: 2em;
            height: auto;
        }

        .switch__knob-neon circle {
            opacity: 0;
            stroke-dasharray: 0 90.32 0 54.19;
            transition: opacity var(--trans-dur) steps(1, end), stroke-dasharray var(--trans-dur) var(--trans-timing);
        }

        .switch__knob-shadow {
            border-radius: 50%;
            box-shadow: 0.125em 0.125em 0.125em hsla(0, 0%, 0%, 0.9);
            display: block;
            position: absolute;
            top: 0.5em;
            left: 0.5em;
            width: 2em;
            height: 2em;
            transition: transform var(--trans-dur) var(--trans-timing);
        }

        .switch__led {
            background-color: hsl(var(--off-hue), 90%, 70%);
            border-radius: 50%;
            box-shadow: 0 -0.0625em 0.0625em hsl(var(--off-hue), 90%, 40%) inset, 0 0 0.125em hsla(var(--off-hue), 90%, 70%, 0.3), 0 0 0.125em hsla(var(--off-hue), 90%, 70%, 0.3), 0.125em 0.125em 0.125em hsla(0, 0%, 0%, 0.5);
            display: block;
            position: absolute;
            top: 0;
            left: 0;
            width: 0.25em;
            height: 0.25em;
            transition: background-color var(--trans-dur) var(--trans-timing), box-shadow var(--trans-dur) var(--trans-timing);
        }

        .switch__text {
            overflow: hidden;
            position: absolute;
            width: 1px;
            height: 1px;
        }

        .switch__input:checked~.switch__led {
            background-color: hsl(var(--on-hue1), 90%, 70%);
            box-shadow: 0 -0.0625em 0.0625em hsl(var(--on-hue1), 90%, 40%) inset, 0 -0.125em 0.125em hsla(var(--on-hue1), 90%, 70%, 0.3), 0 0.125em 0.125em hsla(var(--on-hue1), 90%, 70%, 0.3), 0.125em 0.125em 0.125em hsla(0, 0%, 0%, 0.5);
        }

        .switch__input:checked~.switch__base-neon path {
            stroke-dasharray: 52.13 0 52.13;
        }

        .switch__input:checked~.switch__knob-shadow,
        .switch__input:checked~.switch__knob-container .switch__knob {
            transform: translateX(100%);
        }

        .switch__input:checked~.switch__knob-container .switch__knob-neon circle {
            opacity: 1;
            stroke-dasharray: 45.16 0 45.16 54.19;
            transition-timing-function: steps(1, start), var(--trans-timing);
        }
        .btn-box{
            /* width: 2.5em; */
            position: absolute;
            top: 0.1em;
            left: 50%;
            transform: translateX(-50%);
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
        }
        .btn-box .btn {
            width: 10em;
            background-color: rgb(32, 93, 224);
            border: none;
            color: white;
            padding: 15px 32px;
            text-align: center;
            text-decoration: none;
            display: inline-block;
            font-size: 0.3em;
            margin: 4px 2px;
            cursor: pointer;
        }
        .btn-box #demo {
            font-size: 0.3em;
        }
    </style>
</head>

<body>
    <div class="btn-box">
        <button class="btn" type="button" onclick="callArkTS()">Click Me!</button>
        <p id="demo"></p>
    </div>
    <label class="switch">
        <input id="switch" class="switch__input" type="checkbox" role="switch">
        <span class="switch__base-outer"></span>
        <span class="switch__base-inner"></span>
        <svg class="switch__base-neon" viewBox="0 0 40 24" width="40px" height="24px">
            <defs>
                <filter id="switch-glow">
                    <feGaussianBlur result="coloredBlur" stddeviation="1"></feGaussianBlur>
                    <feMerge>
                        <feMergeNode in="coloredBlur"></feMergeNode>
                        <feMergeNode in="SourceGraphic"></feMergeNode>
                    </feMerge>
                </filter>
                <linearGradient id="switch-gradient1" x1="0" y1="0" x2="1" y2="0">
                    <stop offset="0%" stop-color="hsl(var(--on-hue1),90%,70%)" />
                    <stop offset="100%" stop-color="hsl(var(--on-hue2),90%,70%)" />
                </linearGradient>
                <linearGradient id="switch-gradient2" x1="0.7" y1="0" x2="0.3" y2="1">
                    <stop offset="25%" stop-color="hsla(var(--on-hue1),90%,70%,0)" />
                    <stop offset="50%" stop-color="hsla(var(--on-hue1),90%,70%,0.3)" />
                    <stop offset="100%" stop-color="hsla(var(--on-hue2),90%,70%,0.3)" />
                </linearGradient>
            </defs>
            <path fill="none" filter="url(#switch-glow)" stroke="url(#switch-gradient1)" stroke-width="1"
                stroke-dasharray="0 104.26 0" stroke-dashoffset="0.01" stroke-linecap="round"
                d="m.5,12C.5,5.649,5.649.5,12,.5h16c6.351,0,11.5,5.149,11.5,11.5s-5.149,11.5-11.5,11.5H12C5.649,23.5.5,18.351.5,12Z" />
        </svg>
        <span class="switch__knob-shadow"></span>
        <span class="switch__knob-container">
            <span class="switch__knob">
                <svg class="switch__knob-neon" viewBox="0 0 48 48" width="48px" height="48px">
                    <circle fill="none" stroke="url(#switch-gradient2)" stroke-dasharray="0 90.32 0 54.19"
                        stroke-linecap="round" stroke-width="1" r="23" cx="24" cy="24"
                        transform="rotate(-112.5,24,24)" />
                </svg>
            </span>
        </span>
        <span class="switch__led"></span>
        <span class="switch__text">Power</span>
    </label>
</body>
<script>
    let switchDom = document.getElementById("switch");

    function callArkTS() {
        let str = window.harmony.test();
        document.getElementById("demo").innerHTML = '鸿蒙传递过来的参数: '+str;
    }

    switchDom.addEventListener("change", function (e) {
        if(e.target.checked){
            window.harmony.changeBtnText('关闭');
        }else{
            window.harmony.changeBtnText('打开');
        }
    });

    function change() {
        switchDom.checked = !switchDom.checked;
    }
</script>
</html>

鸿蒙App代码如下:

// xxx.ets
import web_webview from '@ohos.web.webview';

class WebViewModel {
  btnText: string = '打开';

  constructor() {
  }

  test(): string {
    return 'ArkTS Hello World!';
  }

  // 修改按钮文本
  changeBtnText(value:string){
    this.btnText = value;
  }

}

@Entry
@Component
struct WebComponent {
  webviewController: web_webview.WebviewController = new web_webview.WebviewController();
  // 声明需要注册的对象
  @State vm: WebViewModel = new WebViewModel();

  build() {
    Stack() {
      Column() {
        // 页面内容
        Scroll(){
          Column(){
            // web组件加载本地index.html页面
            Web({ src: $rawfile('index.html'), controller: this.webviewController})
              .domStorageAccess(true)
              .javaScriptAccess(true)
              .onProgressChange((event)=>{
              	// 自行编写加载状态
              })
              // 将对象注入到web端
              .javaScriptProxy({
                object: this.vm,
                name: "harmony",
                methodList: ["test",'changeBtnText'],
                controller: this.webviewController
              })
          }.padding(16)
        }
        .edgeEffect(EdgeEffect.Fade)
        .width('100%')
        .layoutWeight(1)
        .align(Alignment.TopStart)
        Button(this.vm.btnText)
          .width('80%')
          .borderRadius(10)
          .margin({bottom:px2vp(Number(AppStorage.get('safeAreaTopHeight'))) + ''})
          .onClick(() => {
            if(this.vm.btnText === '打开'){
              this.vm.btnText = '关闭';
            }else if(this.vm.btnText === '关闭'){
              this.vm.btnText = '打开';
            }
            this.webviewController.runJavaScript('change()');
          })
      }
      .height('100%')
      .backgroundColor('#F5F5F5')
    }
  }
}

Web组件使用问题

鸿蒙的Web组件加载H5页面会出现很多意外的问题,我这里建议把Web组件的以下两个选项开启,避免问题的产生。

  1. domStorageAccess(true)开启文档对象模型存储接口(DOM Storage API)权限
  2. javaScriptAccess(true)允许执行JavaScript脚本

具体代码如下:

// xxx.ets
import web_webview from '@ohos.web.webview';class WebViewModel {
  constructor() {
  }test(): string {
    return 'ArkTS Hello World!';
  }
}
​
@Entry
@Component
struct WebComponent {
  webviewController: web_webview.WebviewController = new web_webview.WebviewController();
  // 声明需要注册的对象
  @State vm: WebViewModel = new WebViewModel();build() {
    Column() {
      // web组件加载本地index.html页面
      Web({ src: $rawfile('index.html'), controller: this.webviewController})
      	.domStorageAccess(true)
      	.javaScriptAccess(true)
        // 将对象注入到web端
        .javaScriptProxy({
          object: this.vm,
          name: "harmony",
          methodList: ["test"],
          controller: this.webviewController
        })
    }
  }
}

其他选项可参考 鸿蒙Web官网

Harmony OS NEXT版本(接口及解决方案兼容API12版本或以上版本)


http://www.niftyadmin.cn/n/5865301.html

相关文章

Flutter系列教程之(2)——Dart语言快速入门

目录 1.变量与类型 1.1 num类型 1.2 String类型 1.3 Object与Dynamic 1.4 类型判断/转换 1.5 变量和常量 2.方法/函数 3.类、接口、抽象类 3.1 类 3.2 接口 4.集合 4.1 List 4.2 Set 4.3 Map 5.总结 Dart语言的语法和Kotlin、Java有类似之处&#xff0c;这里就通…

ADCS-ESC1漏洞环境构造与利用

原理 ESC1是ADCS中的一个漏洞&#xff0c;利用该漏洞可实现权限提升攻击。在 ESC1 漏洞利用中&#xff0c;攻击者通过一系列操作获取包含域管身份信息的证书后&#xff0c;利用 Rubeus.exe 工具&#xff0c;使用该证书获取 TGT 票据。一旦成功获取 TGT 票据&#xff0c;攻击者…

ubuntu windows双系统踩坑

我有个台式机&#xff0c;先安装的ubuntu&#xff0c;本来想专门用来做开发&#xff0c;后面儿子长大了&#xff0c;给他看了一下星际争霸、魔兽争霸&#xff0c;立马就迷上了。还有一台windows的笔记本&#xff0c;想着可以和他联局域网一起玩&#xff0c;在ubuntu上用wine跑魔…

react使用react-quill 富文本插件、加入handlers富文本不显示解决办法

可以调整图片大小 quill-image-resize-module-react 加入插件quill-image-resize-module-reactQuill.register("modules/imageResize", ImageResize); // 注册图片缩放富文本配置中加入如下const quildConfig {toolbar: {container: [["bold", "ital…

qt:多元素类,容器类,布局类

1.列表 List Widget 属性特点currentRow当前被选中的是第几行count一共有多少行sortingEnabled是否允许排序isWrapping是否允许换行itemAlignment元素的对齐方式selectRectVisible被选中的元素矩形是否可见spacing元素之间的间隔 方法特点addItem(const QString& label)…

【现代深度学习技术】卷积神经网络 | 图像卷积

【作者主页】Francek Chen 【专栏介绍】 ⌈ ⌈ ⌈PyTorch深度学习 ⌋ ⌋ ⌋ 深度学习 (DL, Deep Learning) 特指基于深层神经网络模型和方法的机器学习。它是在统计机器学习、人工神经网络等算法模型基础上&#xff0c;结合当代大数据和大算力的发展而发展出来的。深度学习最重…

vue框架后遗症∶被遗忘的dom操作

用多了vue、react等前端框架&#xff0c;不得不说用数据驱动视图来开发真的很香&#xff0c;但是也免不了会有不用这些框架的项目&#xff0c;dom操作还是很有必要的&#xff0c;一开始学习网页设计的时候就教过&#xff0c;后面一直开发项目基本上用框架。虽然有些想不起来了&…

VantUI官网更新2025,移动端前端开发

Vant 2 - Mobile UI Components built on Vue https://vant-ui.github.io/vant/v2/#/zh-CN/quickstart Vant 4 - A lightweight, customizable Vue UI library for mobile web apps. https://vant-ui.github.io/vant/#/zh-CN Vant Weapp - 轻量、可靠的小程序 UI 组件库,微…