当前位置: 首页 > news >正文

HarmonyOS NEXT应用开发之ArkWeb同层渲染

介绍

该方案展示了ArkWeb同层渲染:将系统原生组件直接渲染到前端H5页面上,原生组件不仅可以提供H5组件无法实现的一些功能,还能提升用户体验的流畅度

效果图预览

使用说明

  1. 进入页面即可看到同层渲染效果,Text,search,image都是原生组件。

实现思路

  1. 添加权限。
"ohos.permission.INTERNET"
  1. 创建控制器管理绑定的NodeContainer组件。
class SearchNodeController extends NodeController {private rootNode: BuilderNode<[Params]> | undefined | null = null;private embedId : string = "";private surfaceId : string = "";private renderType :NodeRenderType = NodeRenderType.RENDER_componentTypeDISPLAY;private componentWidth : number = 0;private componentHeight : number = 0;private componentType : 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;}/*** 在对应NodeContainer创建的时候调用、或者通过rebuild方法调用刷新*/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});} else {}// 返回FrameNode节点return this.rootNode.getFrameNode();}/*** 设置BuilderNode节点*/setBuilderNode(rootNode: BuilderNode<Params[]> | null): void{this.rootNode = rootNode;}/*** 获取BuilderNode节点*/getBuilderNode(): BuilderNode<[Params]> | undefined | null{return this.rootNode;}/*** 更新BuilderNode节点*/updateNode(arg: Object): void {this.rootNode?.update(arg);}/*** 获取EmbedId*/getEmbedId() : string {return this.embedId;}/*** 将触摸事件派发到rootNode创建出的FrameNode上*/postEvent(event: TouchEvent | undefined) : boolean {return this.rootNode?.postTouchEvent(event) as boolean;}
}
  1. 添加同层渲染的组件。
@Component
struct SearchComponent {
@Prop params: Params;
controller: SearchController = new SearchController();build() {Column() {Column({ space: MARGIN_VERTICAL }) {Text($r('app.string.headline')).fontSize($r('app.string.ohos_id_text_size_body1'))Text($r('app.string.illustrate')).fontSize($r('app.string.ohos_id_text_size_body1'))}// 原生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)// 原生Grid组件,Grid中包含Image和TextGrid() {// 性能知识点:此处数据量确定且数量较少,使用了ForEach,在数据量多的情况下,推荐使用LazyForeEachForEach(PRODUCT_DATA, (item: ProductDataModel, index: number) => {GridItem() {Column({ space: MARGIN_VERTICAL }) {Image(item.uri).width($r('app.integer.image_size'))Row({ space: MARGIN_VERTICAL }) {Text(item.title).fontSize($r('app.string.ohos_id_text_size_body3'))Text(item.price).fontSize($r('app.string.ohos_id_text_size_body3'))}}}})}.columnsTemplate('1fr 1fr') // 2列.rowsTemplate('1fr 1fr ') // 2行.rowsGap($r('app.string.ohos_id_elements_margin_vertical_m')) // 行间距.columnsGap($r('app.string.ohos_id_elements_margin_vertical_m')) // 列间距}}
}
  1. embed标签可以在H5页面中嵌入任何类型的内容,在H5界面上通过embed标签标识同层元素,应用侧会将原生组件渲染到H5页面embed标签所在位置。
<div><div id="bodyId"><!-- 在H5界面上通过embed标签标识同层元素,在应用侧将原生组件渲染到H5页面embed标签所在位置--><embed id="nativeSearch" type = "native/component" width="100%" height="100%" src="view"/></div>
</div>
  1. 通过WebView的enableNativeEmbedMode()控制同层渲染开关,通过onNativeEmbedLifecycleChange获取embed标签的生命周期变化数据。
build(){Column() {Stack() {// 性能知识点:此处componentId项确定且数量较少,使用了ForEach,在数据量多的情况下,推荐使用LazyForeEachForEach(this.componentIdArr, (componentId: string) => {NodeContainer(this.nodeControllerMap.get(componentId));}, (embedId: string) => embedId)// web组件加载本地test.html页面Web({ src: $rawfile("view.html"), controller: this.browserTabController }).backgroundColor($r('app.color.ohos_id_color_sub_background'))// 不允许执行缩放.zoomAccess(false)// Todo: 知识点:通过enableNativeEmbedMode()配置同层渲染开关.enableNativeEmbedMode(true)// Todo: 知识点:通过onNativeEmbedLifecycleChange获取embed标签的生命周期变化数据.onNativeEmbedLifecycleChange((embed) => {// 获取web侧embed元素的idconst componentId = embed.info?.id?.toString() as stringif (embed.status === NativeEmbedStatus.CREATE) {// 创建节点控制器,设置参数并rebuildlet nodeController = new SearchNodeController();// 外接纹理与WebView同层渲染nodeController.setRenderOption({surfaceId : embed.surfaceId as string, type : embed.info?.type as string, renderType : NodeRenderType.RENDER_componentTypeTEXTURE, embedId : embed.embedId as string, width : px2vp(embed.info?.width), height : px2vp(embed.info?.height)});nodeController.rebuild();// 根据web传入的embed的id属性作为key,将nodeController存入mapthis.nodeControllerMap.set(componentId, nodeController);// 将web传入的embed的id属性存入@State状态数组变量中,用于动态创建nodeContainer节点容器,需要将push动作放在set之后this.componentIdArr.push(componentId);} else if (embed.status === NativeEmbedStatus.UPDATE) {let nodeController = this.nodeControllerMap.get(componentId);nodeController?.updateNode({text: 'update', width: px2vp(embed.info?.width), height: px2vp(embed.info?.height)} as ESObject);nodeController?.rebuild();} else {let nodeController = this.nodeControllerMap.get(componentId);nodeController?.setBuilderNode(null);nodeController?.rebuild();}})// 获取同层渲染组件触摸事件信息.onNativeEmbedGestureEvent((touch) => {this.componentIdArr.forEach((componentId: string) => {let nodeController = this.nodeControllerMap.get(componentId);if (nodeController?.getEmbedId() === touch.embedId) {nodeController?.postEvent(touch.touchEvent);}})})}}
}
  1. h5侧通过id名获取embed标签信息,并通过embed标签添加同层渲染界面的touch监听事件;应用侧添加onNativeEmbedGestureEvent回调使得手指触摸到embed标签时能获取到触摸事件信息。
let nativeEmbed = {// 通过id名获取embed标签nativeSearch : document.getElementById('nativeSearch'),// 事件events:{},// 初始化init:function(){let self = this;// 添加touch的监听事件self.nativeSearch.addEventListener('touchstart', self.events, false);}
};
nativeEmbed.init();

Web({ src: $rawfile("view.html"), controller: this.browserTabController })// 获取同层渲染组件触摸事件信息.onNativeEmbedGestureEvent((touch) => {this.componentIdArr.forEach((componentId: string) => {let nodeController = this.nodeControllerMap.get(componentId);if (nodeController?.getEmbedId() === touch.embedId) {nodeController?.postEvent(touch.touchEvent);}})})

高性能知识点

ArkWeb同层渲染原生组件,原生组件不仅可以提供H5组件无法实现的一些功能,还能提升用户体验的流畅度;同层渲染节点上下树,实现节点复用,节省节点重复开销。

工程结构&模块类型

nativeembed                            // har类型
|---mock
|   |---GoodsMock.ets                  // 数据源
|---model
|   |---GoodsModel.ets                 // 数据类
|---view
|   |---NativeEmbedView.ets            // 视图层

模块依赖

本实例依赖common模块来实现资源的调用。 依赖动态路由模块来实现页面的动态加载。

参考资料

  1. Web
  2. BuilderNode
  3. NodeController
  4. ArkWeb(方舟Web)

为了能让大家更好的学习鸿蒙(HarmonyOS NEXT)开发技术,这边特意整理了《鸿蒙开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05

《鸿蒙开发学习手册》:

如何快速入门:https://qr21.cn/FV7h05

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. ……

开发基础知识:https://qr21.cn/FV7h05

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. ……

基于ArkTS 开发:https://qr21.cn/FV7h05

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. ……

鸿蒙开发面试真题(含参考答案):https://qr18.cn/F781PH

鸿蒙开发面试大盘集篇(共计319页):https://qr18.cn/F781PH

1.项目开发必备面试题
2.性能优化方向
3.架构方向
4.鸿蒙开发系统底层方向
5.鸿蒙音视频开发方向
6.鸿蒙车载开发方向
7.鸿蒙南向开发方向

相关文章:

  • 自动驾驶轨迹规划之时空语义走廊(一)
  • 鸿蒙Harmony应用开发—ArkTS-ForEach:循环渲染
  • Linux环境变量【终】
  • element-ui checkbox 组件源码分享
  • 10、chrome拓展程序的实现
  • 01分布式搜索引擎ES
  • GT20L16S1Y标准汉字字库芯片完全解析(2)
  • 基于FPGA的UDP协议栈设计第三章_ARP层设计
  • RESTful架构
  • 零基础-MySQL数据库的基本操作
  • PWM脉宽调制技术
  • 第十节:Vben Admin实战-系统管理之角色管理实现(分页查询,修改)-中
  • creator-webview与Android交互
  • Unity:2D
  • 读算法的陷阱:超级平台、算法垄断与场景欺骗笔记19_前方的路
  • 分享的文章《人生如棋》
  • 3.7、@ResponseBody 和 @RestController
  • Apache Pulsar 2.1 重磅发布
  • gops —— Go 程序诊断分析工具
  • jquery cookie
  • js ES6 求数组的交集,并集,还有差集
  • JS正则表达式精简教程(JavaScript RegExp 对象)
  • Laravel Telescope:优雅的应用调试工具
  • Netty 框架总结「ChannelHandler 及 EventLoop」
  • nginx(二):进阶配置介绍--rewrite用法,压缩,https虚拟主机等
  • Python十分钟制作属于你自己的个性logo
  • React 快速上手 - 07 前端路由 react-router
  • React-Native - 收藏集 - 掘金
  • Terraform入门 - 1. 安装Terraform
  • vue 个人积累(使用工具,组件)
  • 产品三维模型在线预览
  • 从零到一:用Phaser.js写意地开发小游戏(Chapter 3 - 加载游戏资源)
  • 对JS继承的一点思考
  • 简单易用的leetcode开发测试工具(npm)
  • 罗辑思维在全链路压测方面的实践和工作笔记
  • 区块链技术特点之去中心化特性
  • 实现简单的正则表达式引擎
  • 数据结构java版之冒泡排序及优化
  • 思维导图—你不知道的JavaScript中卷
  • 算法-图和图算法
  • 腾讯优测优分享 | 你是否体验过Android手机插入耳机后仍外放的尴尬?
  • 想晋级高级工程师只知道表面是不够的!Git内部原理介绍
  • ​ 无限可能性的探索:Amazon Lightsail轻量应用服务器引领数字化时代创新发展
  • #13 yum、编译安装与sed命令的使用
  • #QT(智能家居界面-界面切换)
  • ${ }的特别功能
  • (007)XHTML文档之标题——h1~h6
  • (1)(1.13) SiK无线电高级配置(六)
  • (26)4.7 字符函数和字符串函数
  • (DenseNet)Densely Connected Convolutional Networks--Gao Huang
  • (Pytorch框架)神经网络输出维度调试,做出我们自己的网络来!!(详细教程~)
  • (zt)最盛行的警世狂言(爆笑)
  • (二)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (附源码)ssm考生评分系统 毕业设计 071114
  • (淘宝无限适配)手机端rem布局详解(转载非原创)