鸿蒙Web组件与H5通信的高级方式

本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新

一、postMessage基本用法

postMessage是Web组件与H5页面通信的高级方式,相比runJavaScriptjavaScriptProxy,它更适合大数据量和频繁通信的场景。

1. 基本通信流程

鸿蒙原生侧代码

// 创建Web控制器
private webController: webview.WebviewController = new webview.WebviewController();

// 发送消息到H5
sendToH5() {
  const message = {
    type: 'native_message',
    data: { value: '来自鸿蒙的消息' }
  };
  
  // 方式1:直接发送字符串
  this.webController.postMessage(JSON.stringify(message));
  
  // 方式2:通过端口发送(推荐)
  const [port1, port2] = this.webController.createWebMessagePorts();
  port1.postMessageEvent(JSON.stringify(message));
}

二、双向通信实现

1. 使用消息端口建立双向通道

鸿蒙侧完整示例

@Entry
@Component
struct WebComponent {
  private webController: webview.WebviewController = new webview.WebviewController();
  private h5Port: webview.WebMessagePort; // 保存H5端口

  build() {
    Column() {
      Web({
        src: $rawfile('h5page.html'),
        controller: this.webController
      })
      .onPageEnd(() => {
        this.setupMessagePort();
      })
    }
  }

  // 建立消息端口通信
  private setupMessagePort() {
    // 创建一对消息端口
    const [nativePort, h5Port] = this.webController.createWebMessagePorts();
    this.h5Port = h5Port;
    
    // 设置消息监听
    nativePort.onMessageEvent((message: webview.WebMessage) => {
      console.log('收到H5消息:', JSON.parse(message.data));
      
      // 回复消息
      const response = {
        type: 'ack',
        data: '已收到你的消息',
        timestamp: new Date().getTime()
      };
      nativePort.postMessageEvent(JSON.stringify(response));
    });
    
    // 将端口传递给H5
    this.webController.postMessage('init_port', [h5Port]);
  }
}

H5侧完整实现

// 存储通信端口
let nativePort = null;

// 初始化通信
window.addEventListener('message', (event) => {
  if (event.data === 'init_port') {
    // 获取鸿蒙传递过来的端口
    nativePort = event.ports[0];
    
    // 设置消息监听
    nativePort.onmessage = (msgEvent) => {
      const message = JSON.parse(msgEvent.data);
      console.log('收到鸿蒙回复:', message);
    };
    
    // 测试发送消息
    setInterval(() => {
      if (nativePort) {
        nativePort.postMessage({
          type: 'heartbeat',
          data: 'H5心跳消息',
          timestamp: Date.now()
        });
      }
    }, 3000);
  }
});

三、高级应用场景

1. 实时数据流传输

鸿蒙侧传感器数据实时传输

// 创建消息端口
const [sensorPort, h5Port] = this.webController.createWebMessagePorts();

// 注册传感器监听
sensor.on('change', (data) => {
  sensorPort.postMessageEvent(JSON.stringify({
    type: 'sensor_data',
    data: {
      x: data.x,
      y: data.y,
      z: data.z,
      timestamp: Date.now()
    }
  }));
});

// 将端口传递给H5
this.webController.postMessage('sensor_port_init', [h5Port]);

H5侧实时可视化

let chart = initChart();

window.addEventListener('message', (event) => {
  if (event.data === 'sensor_port_init') {
    const port = event.ports[0];
    
    port.onmessage = (event) => {
      const data = JSON.parse(event.data);
      if (data.type === 'sensor_data') {
        chart.update({
          x: data.x,
          y: data.y,
          z: data.z
        });
      }
    };
  }
});

四、安全注意事项

  1. 验证消息来源
   window.addEventListener('message', (event) => {
     // 确保消息来自父窗口
     if (event.source !== window.parent) return;
   });

     2. 限制目标域(加载远程网页时):

   Web({
     src: 'https://trusted-site.com',
     controller: this.webController
   })
   .domain('xxx-xxx.com') // 限制域名

     3. 数据校验:

   port.onMessageEvent((message) => {
     const data = JSON.parse(message.data);
     
     if (!isValid(data.type)) {
       console.error('非法消息类型');
       return;
     }
   });

五、常见问题解决

1. 消息未收到怎么办?

  • 检查postMessage是否在页面加载完成后调用(建议在onPageEnd回调中初始化)
  • 确认H5已正确添加message事件监听
  • 检查消息端口是否已正确传递

2. 如何调试消息通信?

鸿蒙侧调试

port.onMessageEvent((message) => {
  console.log('收到消息:', message.data);
  // 在DevEco Studio的Log窗口中查看
});

 H5侧调试

window.addEventListener('message', (event) => {
  console.log('原始消息事件:', event);
  // 在浏览器开发者工具中查看
});

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值