纯血鸿蒙APP实战开发——预渲染实现Web页面瞬开效果

介绍

为了便于大家在使用本案例集时能够更详细的了解各个案例,本案例基于Web预渲染实现了案例介绍功能,即应用右下角的问号icon。

效果图预览

使用说明

  1. 因为直接加载的线上README,因此本功能需联网使用
  2. 点击icon,即会弹出对应案例的README
  3. 按钮可拖动
  4. 返回或下拉bindSheet上方的dragBar可隐藏帮助页

案例适配说明

为确保案例正确显示其README,请确保entry模块的依赖中@ohos/xxx中的xxx与案例目录名相同

实现思路

  1. 使用Stack承载Navigation,从而使得icon能够在应用的各个案例(NavDestination承载)上显示。源码见EntryView.ets

    typescript 复制代码
    Stack() {
      Navigation(this.pageStack) {
      //...
      }
      // 帮助功能:在每个案例的右下角添加"帮助"功能
      HelperView()
    }
  2. 使用BindSheet+WebView加载仓上各模块README。源码见HelperView.ets

    typescript 复制代码
    build() {
      Image($r("app.media.help"))
        .bindSheet($$this.isShowReadMe, this.buildReadMeSheet(), {
          //...
      })
    }
    
    @Builder
    buildReadMeSheet(): void {
      //...
    }
  3. 使用webview预渲染提升用户体验,复用webview实例减少资源占用。源码见NWebUtils.ets

    typescript 复制代码
    /**
     * Builder中为动态组件的具体组件内容
     * 调用onActive,开启渲染
     */
    @Builder
    function WebBuilder(data: Data) {
      Web({ src: data.url, controller: data.controller })
        .onPageBegin(() => {
          data.controller.onActive();
        })
        .width($r("app.string.full_size"))
        .height($r("app.string.full_size"))
    }
    
    
    const wrap: WrappedBuilder<Data[]> = wrapBuilder<Data[]>(WebBuilder);
    
    /**
     * 用于控制和反馈对应的NodeContainer上的节点的行为,需要与NodeContainer一起使用
     */
    export class NWebNodeController extends NodeController {
      private rootNode: BuilderNode<Data[]> | null = null;
    
      /**
       * 必须要重写的方法,用于构建节点数、返回节点挂载在对应NodeContainer中
       * 在对应NodeContainer创建的时候调用、或者通过rebuild方法调用刷新
       */
      makeNode(uiContext: UIContext): FrameNode | null {
        if (this.rootNode) {
          return this.rootNode.getFrameNode();
        }
        return null; // 返回null控制动态组件脱离绑定节点
      }
    
      /**
       * 自定义函数,可作为初始化函数使用
       * 通过UIContext初始化BuilderNode,再通过BuilderNode中的build接口初始化@Builder中的内容
       */
      initWeb(url: string, uiContext: UIContext, controller: WebviewController) {
        if (this.rootNode) {
          return;
        }
        // 创建节点与动态web组件
        this.rootNode = new BuilderNode(uiContext);
        this.rootNode.build(wrap, { url: url, controller: controller });
      }
    }
    
    interface CurrentNode {
      url: string | null;
      webController: webview.WebviewController | null;
      nWebController: NWebNodeController | null;
      lastNetAvailable: boolean;
    }
    
    /**
     * 复用webview
     */
    function loadUrl(url: string): void {
      if (currentNode.webController) {
        currentNode.url = url;
        currentNode.webController.loadUrl(url);
      }
    }
    
    // 当前的Node
    const currentNode: CurrentNode = { url: null, nWebController: null, webController: null, lastNetAvailable: true };
    
    /**
     * 销毁相关资源
     */
    export function clearHelperWeb() {
      currentNode.url = null;
      currentNode.webController = null;
      currentNode.nWebController = null;
    }
    
    /**
     * 创建web实例,如果已经存在web实例,复用
     * @param url
     * @param uiContext
     */
    export function createNWeb(url: string, uiContext: UIContext): void {
      if (currentNode.webController && currentNode.nWebController && currentNode.url !== url || !currentNode.lastNetAvailable) {
        loadUrl(url);
        currentNode.lastNetAvailable = connection.hasDefaultNetSync();
        return;
      }
      clearHelperWeb();
      let baseNode = new NWebNodeController();
      let controller = new webview.WebviewController();
      // 初始化自定义web组件
      baseNode.initWeb(url, uiContext, controller);
      currentNode.url = url;
      currentNode.webController = controller;
      currentNode.nWebController = baseNode;
      currentNode.lastNetAvailable = connection.hasDefaultNetSync();
    }
    
    /**
     * 获取NodeController
     */
    export function getNWeb(url: string): NWebNodeController | null {
      if (currentNode.url != url || !currentNode.lastNetAvailable) {
        loadUrl(url);
      }
      currentNode.lastNetAvailable = connection.hasDefaultNetSync();
      return currentNode.nWebController;
    }
    
    /**
     * 停止页面加载:当url频繁切换时使用
     */
    export function stopWebLoad(): void {
      if (currentNode.url && currentNode.webController) {
        currentNode.webController.stop();
      }
    }
  4. 监听NavPathStack的变更,及时切换url。源码见HelperView.ets

    typescript 复制代码
    onPageStackChange(): void {
      if (!this.pageStack.size()) {
        this.helperUrl = HelperConstants.HELPER_URL_HOME;
      } else {
        const size: number = this.pageStack.size();
        let moduleName: string = this.pageStack.getAllPathName()[size-1].split('/')[1];
        this.helperUrl = HelperConstants.HELPER_URL_PROTOTYPE.replace("{placeholder}", moduleName);
      }
    }

参考资料

  1. web预渲染
  2. bindSheet

鸿蒙全栈开发全新学习指南

也为了积极培养鸿蒙生态人才,让大家都能学习到鸿蒙开发最新的技术,针对一些在职人员、0基础小白、应届生/计算机专业、鸿蒙爱好者等人群,整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线【包含了大APP实战项目开发】

本路线共分为四个阶段:

第一阶段:鸿蒙初中级开发必备技能

第二阶段:鸿蒙南北双向高工技能基础:gitee.com/MNxiaona/733GH

第三阶段:应用开发中高级就业技术

第四阶段:全网首发-工业级南向设备开发就业技术:https://gitee.com/MNxiaona/733GH

《鸿蒙 (Harmony OS)开发学习手册》(共计892页)

如何快速入门?

1.基本概念

2.构建第一个ArkTS应用

3.......

开发基础知识:gitee.com/MNxiaona/733GH

1.应用基础知识

2.配置文件

3.应用数据管理

4.应用安全管理

5.应用隐私保护

6.三方应用调用管控机制

7.资源分类与访问

8.学习ArkTS语言

9.......

基于ArkTS 开发

1.Ability开发

2.UI开发

3.公共事件与通知

4.窗口管理

5.媒体

6.安全

7.网络与链接

8.电话服务

9.数据管理

10.后台任务(Background Task)管理

11.设备管理

12.设备使用信息统计

13.DFX

14.国际化开发

15.折叠屏系列

16.......

鸿蒙开发面试真题(含参考答案):gitee.com/MNxiaona/733GH

鸿蒙入门教学视频:

美团APP实战开发教学:gitee.com/MNxiaona/733GH

写在最后

  • 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
  • 想要获取更多完整鸿蒙最新学习资源,请移步前往小编:gitee.com/MNxiaona/733GH
相关推荐
乐闻x7 分钟前
Vue.js 性能优化指南:掌握 keep-alive 的使用技巧
前端·vue.js·性能优化
一条晒干的咸魚8 分钟前
【Web前端】创建我的第一个 Web 表单
服务器·前端·javascript·json·对象·表单
Amd79424 分钟前
Nuxt.js 应用中的 webpack:compiled 事件钩子
前端·webpack·开发·编译·nuxt.js·事件·钩子
生椰拿铁You32 分钟前
09 —— Webpack搭建开发环境
前端·webpack·node.js
狸克先生44 分钟前
如何用AI写小说(二):Gradio 超简单的网页前端交互
前端·人工智能·chatgpt·交互
baiduopenmap1 小时前
百度世界2024精选公开课:基于地图智能体的导航出行AI应用创新实践
前端·人工智能·百度地图
loooseFish1 小时前
小程序webview我爱死你了 小程序webview和H5通讯
前端
菜牙买菜1 小时前
让安卓也能玩出Element-Plus的表格效果
前端
请叫我欧皇i1 小时前
html本地离线引入vant和vue2(详细步骤)
开发语言·前端·javascript
533_1 小时前
[vue] 深拷贝 lodash cloneDeep
前端·javascript·vue.js