HarmonyOS应用侧与前端页面数据通道建立

一、应用侧调用前端页面函数

应用侧可以通过runJavaScript()方法调用前端页面的JavaScript相关函数。在下面的示例中,点击应用侧的"runJavaScript"按钮时,来触发前端页面的htmlTest()方法。

  • 前端页面代码。
复制代码
<!--` `index.html` `-->`
`<!DOCTYPE` `html>`
`<html>`
`<body>`
`<script>`
    `function` `htmlTest()` `{`
        `console.info('JavaScript Hello World! ');`
    `}`
`</script>`
`</body>`
`</html>`
`

应用侧代码。

复制代码
//` `xxx.ets`
`import` `web_webview` `from` `'@ohos.web.webview';`

`@Entry`
`@Component`
`struct` `WebComponent` `{`
  `webviewController:` `web_webview.WebviewController` `=` `new` `web_webview.WebviewController();`

  `build()` `{`
    `Column()` `{`
      `Web({` `src: $rawfile('index.html'),` `controller:` `this.webviewController})`
      `Button('runJavaScript')`
        `.onClick(()` `=>` `{`
           `this.webviewController.runJavaScript('htmlTest()');`
        `})`
    `}`
  `}`
`}`
`

二、前端页面调用应用侧函数

开发者使用Web组件将应用侧代码注册到前端页面中,注册完成之后,前端页面中使用注册的对象名称就可以调用应用侧的函数,实现在前端页面中调用应用侧方法。

注册应用侧代码有两种方式,一种在Web组件初始化使用调用,使用javaScriptProxy()接口。另外一种在Web组件初始化完成后调用,使用registerJavaScriptProxy()接口。

在下面的示例中,将test()方法注册在前端页面中, 该函数可以在前端页面触发运行。

复制代码
//` `xxx.ets`
`import` `web_webview` `from` `'@ohos.web.webview';`

`@Entry`
`@Component`
`struct` `WebComponent` `{`
  `webviewController:` `web_webview.WebviewController` `=` `new` `web_webview.WebviewController();`
  `// 声明需要注册的对象`
  `testObj` `=` `{`
    `test:` `()` `=>` `{`
      `return` `'ArkTS Hello World!';`
    `}`
  `}`

  `build()` `{`
    `Column()` `{`
      `//` `web组件加载本地index.html页面`
      `Web({` `src: $rawfile('index.html'),` `controller:` `this.webviewController})`
        `// 将对象注入到web端`
        `.javaScriptProxy({`
          `object:` `this.testObj,`
          `name:` `"testObjName",`
          `methodList:` `["test"],`
          `controller:` `this.webviewController`
        `})`
    `}`
  `}`
`}`
`
  • 应用侧使用registerJavaScriptProxy()接口注册。
复制代码
//` `xxx.ets`
`import` `web_webview` `from` `'@ohos.web.webview';`

`@Entry`
`@Component`
`struct` `Index` `{`
  `webviewController:` `web_webview.WebviewController` `=` `new` `web_webview.WebviewController();`
  `testObj` `=` `{`
    `test:` `(data)` `=>` `{`
      `return` `"ArkUI Web Component";`
    `},`
    `toString:` `()` `=>` `{`
      `console.info('Web Component toString');`
    `}`
  `}`

  `build()` `{`
    `Column()` `{`
      `Button('refresh')`
        `.onClick(()` `=>` `{`
          `try` `{`
            `this.webviewController.refresh();`
          `}` `catch` `(error)` `{`
            `console.error(`Errorcode: ${error.code},` `Message: ${error.message}`);`
          `}`
        `})`
      `Button('Register JavaScript To Window')`
        `.onClick(()` `=>` `{`
          `try` `{`
            `this.webviewController.registerJavaScriptProxy(this.testObj,` `"objName",` `["test",` `"toString"]);`
          `}` `catch` `(error)` `{`
            `console.error(`Errorcode: ${error.code},` `Message: ${error.message}`);`
          `}`
        `})`
      `Web({` `src: $rawfile('index.html'),` `controller:` `this.webviewController` `})`
    `}`
  `}`
`}`
`

说明

使用registerJavaScriptProxy()接口注册方法时,注册后需调用refresh()接口生效。

  • index.html前端页面触发应用侧代码。
复制代码
<!--` `index.html` `-->`
`<!DOCTYPE` `html>`
`<html>`
`<body>`
`<button` `type="button"` `onclick="callArkTS()">Click` `Me!</button>`
`<p` `id="demo"></p>`
`<script>`
    `function` `callArkTS()` `{`
        `let` `str` `=` `objName.test();`
        `document.getElementById("demo").innerHTML` `=` `str;`
        `console.info('ArkTS Hello World! :'` `+` `str);`
    `}`
`</script>`
`</body>`
`</html>`
`

三、建立应用侧与前端页面数据通道

前端页面和应用侧之间可以用createWebMessagePorts()接口创建消息端口来实现两端的通信。

在下面的示例中,应用侧页面中通过createWebMessagePorts方法创建消息端口,再把其中一个端口通过postMessage()接口发送到前端页面,便可以在前端页面和应用侧之间互相发送消息。

  • 应用侧代码。
复制代码
//` `xxx.ets`
`import` `web_webview` `from` `'@ohos.web.webview';`

`@Entry`
`@Component`
`struct` `WebComponent` `{`
  `controller:` `web_webview.WebviewController` `=` `new` `web_webview.WebviewController();`
  `ports:` `web_webview.WebMessagePort[];`
`  @State` `sendFromEts:` `string` `=` `'Send this message from ets to HTML';`
`  @State` `receivedFromHtml:` `string` `=` `'Display received message send from HTML';`

  `build()` `{`
    `Column()` `{`
      `// 展示接收到的来自HTML的内容`
      `Text(this.receivedFromHtml)`
      `// 输入框的内容发送到html`
      `TextInput({placeholder:` `'Send this message from ets to HTML'})`
        `.onChange((value:` `string)` `=>` `{`
          `this.sendFromEts` `=` `value;`
        `})`

      `Button('postMessage')`
        `.onClick(()` `=>` `{`
          `try` `{`
            `//` `1、创建两个消息端口。`
            `this.ports` `=` `this.controller.createWebMessagePorts();`
            `//` `2、在应用侧的消息端口(如端口1)上注册回调事件。`
            `this.ports[1].onMessageEvent((result:` `web_webview.WebMessage)` `=>` `{`
              `let` `msg` `=` `'Got msg from HTML:';`
              `if` `(typeof(result)` `===` `'string')` `{`
                `console.info(`received` `string` `message` `from` `html5,` `string` `is: ${result}`);`
                `msg` `=` `msg` `+` `result;`
              `}` `else` `if` `(typeof(result)` `===` `'object')` `{`
                `if` `(result` `instanceof` `ArrayBuffer)` `{`
                  `console.info(`received` `arraybuffer` `from` `html5,` `length` `is: ${result.byteLength}`);`
                  `msg` `=` `msg` `+` `'lenght is '` `+` `result.byteLength;`
                `}` `else` `{`
                  `console.info('not support');`
                `}`
              `}` `else` `{`
                `console.info('not support');`
              `}`
              `this.receivedFromHtml` `=` `msg;`
            `})`
            `//` `3、将另一个消息端口(如端口0)发送到HTML侧,由HTML侧保存并使用。`
            `this.controller.postMessage('__init_port__',` `[this.ports[0]],` `'*');`
          `}` `catch` `(error)` `{`
            `console.error(`ErrorCode: ${error.code},`  `Message: ${error.message}`);`
          `}`
        `})`

      `//` `4、使用应用侧的端口给另一个已经发送到html的端口发送消息。`
      `Button('SendDataToHTML')`
        `.onClick(()` `=>` `{`
          `try` `{`
            `if` `(this.ports` `&&` `this.ports[1])` `{`
              `this.ports[1].postMessageEvent(this.sendFromEts);`
            `}` `else` `{`
              `console.error(`ports` `is` `null,` `Please` `initialize` `first`);`
            `}`
          `}` `catch` `(error)` `{`
            `console.error(`ErrorCode: ${error.code},` `Message: ${error.message}`);`
          `}`
        `})`
      `Web({` `src: $rawfile('xxx.html'),` `controller:` `this.controller` `})`
    `}`
  `}`
`}`
`
  • 前端页面代码。
复制代码
<!--xxx.html-->`
`<!DOCTYPE` `html>`
`<html>`
`<head>`
    `<meta` `name="viewport"` `content="width=device-width, initial-scale=1.0">`
    `<title>WebView` `Message` `Port` `Demo</title>`
`</head>`
`<body>`
    `<h1>WebView` `Message` `Port` `Demo</h1>`
    `<div>`
        `<input` `type="button"` `value="SendToEts"` `onclick="PostMsgToEts(msgFromJS.value);"/><br/>`
        `<input` `id="msgFromJS"` `type="text"` `value="send this message from HTML to ets"/><br/>`
    `</div>`
    `<p` `class="output">display` `received` `message` `send` `from` `ets</p>`
`</body>`
`<script>`
`var` `h5Port;`
`var` `output` `=` `document.querySelector('.output');`
`window.addEventListener('message',` `function` `(event)` `{`
    `if` `(event.data` `===` `'__init_port__')` `{`
        `if` `(event.ports[0]` `!==` `null)` `{`
            `h5Port` `=` `event.ports[0];` `//` `1. 保存从ets侧发送过来的端口`
            `h5Port.onmessage` `=` `function` `(event)` `{`
              `//` `2. 接收ets侧发送过来的消息.`
              `var` `msg` `=` `'Got message from ets:';`
              `var` `result` `=` `event.data;`
              `if` `(typeof(result)` `===` `'string')` `{`
                `console.info(`received` `string` `message` `from` `html5,` `string` `is: ${result}`);`
                `msg` `=` `msg` `+` `result;`
              `}` `else` `if` `(typeof(result)` `===` `'object')` `{`
                `if` `(result` `instanceof` `ArrayBuffer)` `{`
                  `console.info(`received` `arraybuffer` `from` `html5,` `length` `is: ${result.byteLength}`);`
                  `msg` `=` `msg` `+` `'lenght is '` `+` `result.byteLength;`
                `}` `else` `{`
                  `console.info('not support');`
                `}`
              `}` `else` `{`
                `console.info('not support');`
              `}`
              `output.innerHTML` `=` `msg;`
            `}`
        `}`
    `}`
`})`
`//` `3. 使用h5Port往ets侧发送消息.`
`function` `PostMsgToEts(data)` `{`
    `if` `(h5Port)` `{`
      `h5Port.postMessage(data);`
    `}` `else` `{`
      `console.error('h5Port is null, Please initialize first');`
    `}`
`}`
`</script>`
`</html>`
`
相关推荐
也无晴也无风雨1 小时前
深入剖析输入URL按下回车,浏览器做了什么
前端·后端·计算机网络
Martin -Tang2 小时前
Vue 3 中,ref 和 reactive的区别
前端·javascript·vue.js
FakeOccupational3 小时前
nodejs 020: React语法规则 props和state
前端·javascript·react.js
放逐者-保持本心,方可放逐3 小时前
react 组件应用
开发语言·前端·javascript·react.js·前端框架
曹天骄5 小时前
next中服务端组件共享接口数据
前端·javascript·react.js
阮少年、5 小时前
java后台生成模拟聊天截图并返回给前端
java·开发语言·前端
郝晨妤6 小时前
鸿蒙ArkTS和TS有什么区别?
前端·javascript·typescript·鸿蒙
AvatarGiser7 小时前
《ElementPlus 与 ElementUI 差异集合》Icon 图标 More 差异说明
前端·vue.js·elementui
喝旺仔la7 小时前
vue的样式知识点
前端·javascript·vue.js
别忘了微笑_cuicui7 小时前
elementUI中2个日期组件实现开始时间、结束时间(禁用日期面板、控制开始时间不能超过结束时间的时分秒)实现方案
前端·javascript·elementui