1# 建立应用侧与前端页面数据通道 2<!--Kit: ArkWeb--> 3<!--Subsystem: Web--> 4<!--Owner: @aohui--> 5<!--Designer: @yaomingliu--> 6<!--Tester: @ghiker--> 7<!--Adviser: @HelloCrease--> 8 9 10前端页面和应用侧之间可以用[createWebMessagePorts()](../reference/apis-arkweb/arkts-apis-webview-WebviewController.md#createwebmessageports)接口创建消息端口来实现两端的通信。 11 12 13在下面的示例中,应用侧页面中通过createWebMessagePorts方法创建两个消息端口,再把其中一个端口通过[postMessage()](../reference/apis-arkweb/arkts-apis-webview-WebviewController.md#postmessage)接口发送到前端页面,便可以在前端页面和应用侧之间互相发送消息。 14 15 16- 应用侧代码。 17 18 ```ts 19 // xxx.ets 20 import { webview } from '@kit.ArkWeb'; 21 import { BusinessError } from '@kit.BasicServicesKit'; 22 23 @Entry 24 @Component 25 struct WebComponent { 26 controller: webview.WebviewController = new webview.WebviewController(); 27 ports: webview.WebMessagePort[] = []; 28 @State sendFromEts: string = 'Send this message from ets to HTML'; 29 @State receivedFromHtml: string = 'Display received message send from HTML'; 30 31 build() { 32 Column() { 33 // 展示接收到的来自HTML的内容 34 Text(this.receivedFromHtml); 35 // 输入框的内容发送到HTML 36 TextInput({ placeholder: 'Send this message from ets to HTML' }) 37 .onChange((value: string) => { 38 this.sendFromEts = value; 39 }) 40 41 // 该内容可以放在onPageEnd生命周期中调用。 42 Button('postMessage') 43 .onClick(() => { 44 try { 45 // 1、创建两个消息端口。 46 this.ports = this.controller.createWebMessagePorts(); 47 if (this.ports && this.ports[0] && this.ports[1]) { 48 // 2、在应用侧的消息端口(如端口1)上注册回调事件。 49 this.ports[1].onMessageEvent((result: webview.WebMessage) => { 50 let msg = 'Got msg from HTML:'; 51 if (typeof (result) === 'string') { 52 console.info(`received string message from html5, string is: ${result}`); 53 msg = msg + result; 54 } else if (typeof (result) === 'object') { 55 if (result instanceof ArrayBuffer) { 56 console.info(`received arraybuffer from html5, length is: ${result.byteLength}`); 57 msg = msg + 'length is ' + result.byteLength; 58 } else { 59 console.info('not support'); 60 } 61 } else { 62 console.info('not support'); 63 } 64 this.receivedFromHtml = msg; 65 }) 66 // 3、将另一个消息端口(如端口0)发送到HTML侧,由HTML侧保存并使用。 67 this.controller.postMessage('__init_port__', [this.ports[0]], '*'); 68 } else { 69 console.error(`ports is null, Please initialize first`); 70 } 71 } catch (error) { 72 console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`); 73 } 74 }) 75 76 // 4、使用应用侧的端口给另一个已经发送到html的端口发送消息。 77 Button('SendDataToHTML') 78 .onClick(() => { 79 try { 80 if (this.ports && this.ports[1]) { 81 this.ports[1].postMessageEvent(this.sendFromEts); 82 } else { 83 console.error(`ports is null, Please initialize first`); 84 } 85 } catch (error) { 86 console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`); 87 } 88 }) 89 Web({ src: $rawfile('index.html'), controller: this.controller }) 90 } 91 } 92 } 93 ``` 94 95- 前端页面代码。 96 97 ```html 98 <!--index.html--> 99 <!DOCTYPE html> 100 <html> 101 <head> 102 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 103 <title>WebView Message Port Demo</title> 104 </head> 105 <body> 106 <h1>WebView Message Port Demo</h1> 107 <div> 108 <input type="button" value="SendToEts" onclick="PostMsgToEts(msgFromJS.value);"/><br/> 109 <input id="msgFromJS" type="text" value="send this message from HTML to ets"/><br/> 110 </div> 111 <p class="output">display received message send from ets</p> 112 </body> 113 <script> 114 var h5Port; 115 var output = document.querySelector('.output'); 116 window.addEventListener('message', function (event) { 117 if (event.data === '__init_port__') { 118 if (event.ports[0] !== null) { 119 h5Port = event.ports[0]; // 1. 保存从应用侧发送过来的端口。 120 h5Port.onmessage = function (event) { 121 // 2. 接收ets侧发送过来的消息。 122 var msg = 'Got message from ets:'; 123 var result = event.data; 124 if (typeof(result) === 'string') { 125 console.info(`received string message from ets, string is: ${result}`); 126 msg = msg + result; 127 } else if (typeof(result) === 'object') { 128 if (result instanceof ArrayBuffer) { 129 console.info(`received arraybuffer from ets, length is: ${result.byteLength}`); 130 msg = msg + 'length is ' + result.byteLength; 131 } else { 132 console.info('not support'); 133 } 134 } else { 135 console.info('not support'); 136 } 137 output.innerHTML = msg; 138 } 139 } 140 } 141 }) 142 143 // 3. 使用h5Port向应用侧发送消息。 144 function PostMsgToEts(data) { 145 if (h5Port) { 146 h5Port.postMessage(data); 147 } else { 148 console.error('h5Port is null, Please initialize first'); 149 } 150 } 151 </script> 152 </html> 153 ``` 154 155## 常见问题 156 157### 为什么H5向应用侧发送消息接收不到? 158检查传递的数据类型是否正确,WebMessage支持的数据类型有string和ArrayBuffer。 159如果想要传递对象类型则需要将对象类型通过JSON.stringify方法转换为string类型再进行传递。示例如下: 160 161```ts 162 function PostMsgToEts(data) { 163 if (h5Port) { 164 let obj = {name:'exampleName',id:10} 165 h5Port.postMessage(JSON.stringify(obj)); 166 } else { 167 console.error('h5Port is null. Please initialize it first.'); 168 } 169 } 170```