HarmonyOS应用侧与前端页面数据通道建立
一、 应用侧调用前端页面函数
应用侧可以通过runJavaScript()方法调用前端页面的JavaScript相关函数。在下面的示例中,点击应用侧的“runJavaScript”按钮时,来触发前端页面的htmlTest()方法。
● 前端页面代码。
1 2 3 4 5 6 7 8 9 10 11 12 | <!-- index.html --> <!DOCTYPE html> <html> <body> <script> function htmlTest() { console.info( 'JavaScript Hello World! ' ); } </script> </body> </html> |
应用侧代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | // 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()方法注册在前端页面中, 该函数可以在前端页面触发运行。
● javaScriptProxy()接口使用示例如下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | // 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()接口注册。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | // 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前端页面触发应用侧代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <!-- 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()接口发送到前端页面,便可以在前端页面和应用侧之间互相发送消息。
● 应用侧代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | // 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(`portsisnull,Pleaseinitializefirst`); } } catch (error){ console.error(`ErrorCode: ${error.code},Message: ${error.message}`); } }) Web({src: $rawfile( 'xxx.html' ),controller: this .controller}) } } } |
● 前端页面代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | <!--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> |
标签:
HarmonyOS
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!