开发者的混合应用开发新体验

在传统的混合应用开发中,Web组件和原生组件往往存在于不同的层级,这导致了许多性能瓶颈和交互限制。鸿蒙NEXT通过ArkWeb同层渲染技术,完美解决了这一问题,让原生组件能够直接渲染到Web页面中,实现了真正的原生与Web融合。

什么是ArkWeb同层渲染?

ArkWeb同层渲染是鸿蒙OS提供的一项创新技术,它允许将系统原生组件直接渲染到前端H5页面上的原生组件。这不仅能够提供H5组件无法实现的一些功能,还能显著提升用户体验的流畅度。

通过同层渲染,开发者可以在Web页面中使用Video、Button、Text、Image等原生组件,这些组件与Web元素渲染在同一层级,消除了传统混合开发中的层级隔离问题。

核心实现原理

1. 基本架构

ArkWeb同层渲染的实现依赖于几个核心组件:

  • NodeController类:控制和反馈对应的NodeContainer上节点的行为,需要与NodeContainer一起使用。

  • BuilderNode:用于构建节点树,返回节点树挂载在对应的NodeContainer中。

  • embed标签:在H5页面上通过embed标签标识同层元素,应用侧会将原生组件渲染到H5页面embed标签所在位置。

2. 同层渲染流程

实现同层渲染的基本流程如下:

在应用侧:创建一个继承自NodeController的类(如SearchNodeController),并重写makeNode等方法来实现自定义的渲染逻辑。

typescript

class SearchNodeController extends NodeController {
  private rootNode: BuilderNode<[Params]> | undefined | null = null;
  private embedId: string = "";
  // 其他属性...
  
  setRenderOption(params: NodeControllerParams): void {
    this.surfaceId = params.surfaceId;
    this.renderType = params.renderType;
    this.embedId = params.embedId;
    this.componentWidth = params.width;
    this.componentHeight = params.height;
    this.componentType = params.type;
  }
  
  makeNode(uiContext: UIContext): FrameNode | null {
    // 构建节点逻辑
    this.rootNode = new BuilderNode(uiContext, { surfaceId: this.surfaceId, type: this.renderType});
    if (this.componentType === 'native/component') {
      this.rootNode.build(wrapBuilder(searchBuilder), { width: this.componentWidth, height: this.componentHeight});
    }
    return this.rootNode.getFrameNode();
  }
}

在H5页面侧:使用embed标签来标识同层渲染内容。

html

<div>
  <div id="bodyId">
    <embed id="nativeSearch" type="native/component" width="100%" height="100%" src="view"/>
  </div>
</div>

开启同层渲染:通过WebView的enableNativeEmbedMode()方法控制同层渲染开关。

typescript

Web({ src: $rawfile("view.html") })
  .enableNativeEmbedMode(true)
  .onNativeEmbedLifecycleChange((embed) => { /* ... */ })

实战示例:创建一个同层渲染应用

下面是一个简单的同层渲染示例,展示了如何在H5页面中嵌入原生搜索组件:

1. 添加权限

首先在module.json5文件中添加Internet权限:

json

{
  "module": {
    "requestPermissions": [
      {
        "name": "ohos.permission.INTERNET"
      }
    ]
  }
}

2. 创建原生组件

typescript

@Component
struct SearchComponent {
  @Prop params: Params;
  controller: SearchController = new SearchController();
  
  build() {
    Column() {
      // 原生Text组件
      Text($r('app.string.mall')).fontSize($r('app.string.ohos_id_text_size_body1'))
      
      // 原生Search组件
      Search({ placeholder: 'Type to search...', controller: this.controller })
        .searchButton(SEARCH_BUTTON)
        
      // 其他原生组件...
    }
  }
}

3. 处理同层渲染生命周期

通过onNativeEmbedLifecycleChange获取embed标签的生命周期变化数据:

typescript

.onNativeEmbedLifecycleChange((embed) => {
  if (embed.info.type !== 'native/component') {
    return;
  }
  
  if (embed.status === 'add') {
    // 创建节点控制器
    const controller = new SearchNodeController();
    controller.setRenderOption({
      surfaceId: embed.info.surfaceId,
      renderType: embed.info.renderType,
      embedId: embed.info.embedId,
      width: embed.info.width,
      height: embed.info.height,
      type: embed.info.type
    });
    
    // 将控制器添加到管理Map中
    this.nodeControllerMap.set(embed.info.embedId, controller);
  } else if (embed.status === 'remove') {
    // 移除节点控制器
    const controller = this.nodeControllerMap.get(embed.info.embedId);
    if (controller) {
      controller.setDestroy(true);
      this.nodeControllerMap.delete(embed.info.embedId);
    }
  }
})

处理宽高适配问题

在实际开发中,可能会遇到H5中设置的宽高与同层渲染回调中拿到的宽高不一致的问题。这是因为H5中的px单位表示屏幕上的一个像素点,与屏幕分辨率有关,而通过同层渲染回调拿到的宽高是渲染组件所占当前设备的实际像素点。

解决方案是在H5页面中添加viewport meta标签:

html

<meta name="viewport" content="width=device-width, initial-scale=1.0">

并根据实际像素比进行调整(例如,如果像素比是3.25,要在回调中拿到的高度为1000,就需要在H5的embed中设置高度1000/3.25)。

性能优化建议

ArkWeb同层渲染不仅提供了更好的用户体验,也在性能方面做了诸多优化:

  1. 节点复用:同层渲染节点上下树,实现节点复用,节省节点重复开销。

  2. 灵活控制:通过ArkWebController类中的setLayerType方法可以设置WebView的渲染层类型,包括是否启用同层渲染。

  3. 触摸事件处理:通过postEvent方法将触摸事件派发到rootNode创建出的FrameNode上。

typescript

let webController: webView.ArkWebController = webView.getWebController();
webController.setLayerType(LayerType.LAYER_TYPE_SOFTWARE); // 禁用同层渲染
// webController.setLayerType(LayerType.LAYER_TYPE_HARDWARE); // 启用同层渲染

应用场景

ArkWeb同层渲染技术在以下场景中特别有用:

  1. 视频播放器:在Web页面中嵌入原生视频播放器,提供更流畅的视频播放体验。

  2. 复杂表单:在Web表单中使用原生表单组件,提高表单的响应速度和用户体验。

  3. 游戏界面:在Web游戏中嵌入原生UI元素,实现更复杂的交互效果。

  4. 地图应用:在地图Web页面中嵌入原生控件,提供更流畅的地图操作体验。

总结

鸿蒙NEXT的ArkWeb同层渲染技术打破了传统Web与原生开发的界限,让开发者能够充分利用原生组件的性能优势和Web开发的灵活性。通过本文的介绍,相信你已经对ArkWeb同层渲染有了基本的了解,并能够开始在自己的项目中应用这一技术。

随着鸿蒙生态的不断发展,ArkWeb同层渲染将会在更多场景中发挥重要作用,为用户带来更加流畅和统一的应用体验。无论是新项目的开发还是现有项目的鸿蒙化改造,ArkWeb同层渲染都值得开发者深入学习和应用。

更多关于ArkWeb同层渲染的示例代码和详细实现,可以参考鸿蒙官方文档或相关的示例工程

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐