> 技术文档 > 鸿蒙ArkTS页面如何与H5页面交互?_h5和鸿蒙交互

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


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

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

先看效果

鸿蒙ArkTS页面如何与H5页面交互?_h5和鸿蒙交互
功能介绍

  • 点击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.etsimport web_webview from \'@ohos.web.webview\';class WebViewModel { btnText: string = \'打开\'; constructor() { } test(): string { return \'ArkTS Hello World!\'; } // 修改按钮文本 changeBtnText(value:string){ this.btnText = value; }}@Entry@Componentstruct 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.etsimport web_webview from \'@ohos.web.webview\';class WebViewModel { constructor() { }test(): string { return \'ArkTS Hello World!\'; }}​@Entry@Componentstruct 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版本或以上版本)