鸿蒙(HarmonyOS)性能优化—Web开发常见问题

567 篇文章 2 订阅
555 篇文章 0 订阅

H5页面如何与ArkTS交互(API 10)

问题现象

目前javaScriptProxy仅支持同步调用,异步调用无法获取执行结果。

解决措施

对javaScriptProxy和runJavaScript封装,实现JSBridge通信方案。适用于H5调用原生侧函数。使用Web组件javaScriptProxy将原生侧接口注入到H5的window对象上,通过runJavaScript接口执行JS脚本到H5中,并在回调中获取脚本执行结果。具体调用流程如下图所示:

  • 首先通过Web组件的javaScriptProxy属性,将JSBridgeHandle对象注册到H5的window上,作为H5调用原生的通道。当H5开始加载时,在onPageBegin生命周期中调用initJSBridge()方法初始化JSBridge。

    // javaScriptProxy对象
    public get javaScriptProxy() {
        return {
            object: {
                call: this.call
            },
            name: "JSBridgeHandle",
            methodList: ['call'],
            controller: this.controller,
        }
    }
    
    // 使用Web组件加载H5页面
    @Component
    struct JsProxy {
      private controller: WebviewController = new WebView.WebviewController()
      private jsBridge: JSBridge = new JSBridge(this.controller)
      build() {
        Column(){
          Web({ src: $rawfile('index.html'), controller: this.controller })
            .javaScriptProxy(this.jsBridge.javaScriptProxy)
            .onPageBegin(() => {
              this.jsBridge.initJSBridge()
            })
        }
      }
    }
    
  • 在initJSBridge方法中,通过webviewControll.runJavaScript()将JSBridge初始化脚本注入H5执行。当H5调用时,生成window.callID标识回调函数,将callID与调用参数使用JSBridgeHandle.call传到原生侧。通过JSBridgeCallback接收原生侧执行的结果,根据callID找到对应callback执行并且释放内存。

    // bridgeKey与bridgeMethod动态生成H5侧调用的入口
    bridgeKey: string = 'JSBridge'
    bridgeMethod: string = 'call'
    // 初始化脚本注入H5侧
    public initJSBridge() {
        try {
            this.controller.runJavaScript(`
                // 接收原生侧结果,执行callback
                function JSBridgeCallback(id, params){
                    window.JSBridgeMap[id](params)
                };
                // 声明调用入口
                window.${this.bridgeKey} = {
                    ${this.bridgeMethod}(method, params, callback){
                        window.JSBridgeMap[id] = callback || (() => {});
                        JSBridgeHandle.call(method, JSON.stringify(paramsObj));
                    },
                }`)
        }
    }
    
  • JSBridgeHandle.call()是H5调用原生接口的统一入口,在该方法中根据H5调用的方法名,匹配到对应接口去调用。调用结束后通过this.callback()方法将调用结果返回H5。callback方法中使用webviewControll.runJavaScript()调用H5的JSBridgeCallback回传callID和调用结果。

    // call方法调用原生侧方法,接收结果
    private call = (fun, params) => {
        try {
            const paramsObj = JSON.parse(params)
            const events = this.exposeManage.methodMap.get(fun)
            const results = []
            events.forEach(callFun => {
                results.push(callFun(paramsObj.data))
            })
            Promise.all(results.filter(i => !!i)).then(res => {
                this.callback(paramsObj.callID, res.length > 1 ? res : res[0])
            })
        }
    }
    
    // 通过runJavaScript调用JSBridgeCallback执行回调
    private callback(id, data) {
        this.controller.runJavaScript(`__JSBridgeCallback__("${id}", ${JSON.stringify(data)})`);
    }
    

Web组件的onUrlLoadIntercept返回结果是否影响onInterceptRequest(API 9)

解决措施

Web组件的onUrlLoadIntercept的不同返回结果对应不同的操作:

  • onUrlLoadIntercept返回true则直接拦截URL请求。

  • onUrlLoadIntercept返回false走onInterceptRequest回调。

为什么Web组件的onKeyEvent键盘事件不生效(API 9)

问题现象

Web组件设置onKeyEvent监听键盘事件,键盘按下或抬起该事件不触发。

解决措施

onKeyEvent为通用事件,当前Web组件不支持通用事件。Web组件监听键盘事件可以使用onInterceptKeyEvent回调函数。

onInterceptRequest拦截URL并自定义HTML文件,页面加载失败(API 9)

问题现象

onInterceptRequest拦截页面Web的src的链接后返回自定义HTML,但是自定义HTML文件里面的script标签里的内容没有加载。

解决措施

设置拦截器时,如果只设置setResponseData,内核将无法识别到这是个HTML文件,需要同时设置setResponseEncoding、setResponseMimeType、setResponseHeader等参数。

代码示例

Web({ src: 'www.example.com', controller: this.controller })
  .onInterceptRequest((event) => {
    console.log('url:' + event.request.getRequestUrl())
    this.responseweb = new WebResourceResponse();
    var head1:Header = {
      headerKey:"Connection",
      headerValue:"keep-alive"
    }
    var length = this.heads.push(head1)
    this.responseweb.setResponseHeader(this.heads)
    this.responseweb.setResponseData(this.webdata)
    this.responseweb.setResponseEncoding('utf-8')
    this.responseweb.setResponseMimeType('text/html')
    this.responseweb.setResponseCode(200)
    this.responseweb.setReasonMessage('OK')
    return this.responseweb
})

如何在ArkTS代码中执行HTML内的JS函数(API 9)

解决措施

通过WebviewController中runJavaScript方法异步执行JavaScript脚本,并通过回调方式获取执行结果。

说明: runJavaScript需要在loadUrl完成后,比如onPageEnd中调用。

使用Web组件加载本地网页时,如何在本地网页中调用ArkTS中的函数(API 9)

解决措施

  1. 准备一个html文件,例如:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
    </head>
    <body>
        <h1>标题</h1>
        <h5 id="h5"></h5>
        <h5 id = "h6"></h5>
        <button onclick="handleFromH5">调用Arkts的方法</button>
        <script type="text/javascript">
            function handleFromH5(){
                let result = window.objName.test();
                document.getElementById('h6').innerHTML = result;
            }
        </script>
    </body>
    </html>
    
  2. 在ArkTs中使用JavaScriptProxy方法将ArkTs里的对象注册到H5的window对象中,然后在h5中使用window对象调用该方法。比如下面例子,在ArkTs中将testObj这个对象以别名objName注册到h5的window对象上,在上面的h5中就可以使用window.objName去访问这个对象。

Web组件domStorageAccess属性设置(API 9)

解决措施

设置是否开启文档对象模型存储接口(DOM Storage API)权限,默认未开启,控制web网页中localStorage的使用,对sessionStorage未做控制

如何解决Web组件加载的HTML页面内检测网络状态失败(API 9)

问题现象

在HTML页面内通过window.navigator.onLine获取网络状态,联网和断网情况下均为false。

解决措施

配置应用获取网络信息权限: ohos.permission.GET_NETWORK_INFO

如何自定义拼接设置UserAgent参数(API 9)

解决措施

默认UserAgent需要通过WebviewController获取。WebviewController对象必须在Web组件绑定后,才能调用WebviewController上的方法getUserAgent获取默认UserAgent。因此在页面加载前通过自定义字符串拼接修改UserAgent,可采用此方式:

  1. 使用@State定义初始UserAgent,绑定到Web组件;

  2. 在Web组件的onUrlLoadIntercept回调中,通过WebviewController.getUserAgent()获取默认UserAgent,并修改Web组件绑定的UserAgent

代码示例

import web_webview from '@ohos.web.webview'
@Entry
@Component
struct Index {
  private controller: web_webview.WebviewController = new web_webview.WebviewController()
  @State userAgentPa: string = ''
  build() {
    Row() {
      Column() {
        Web({ src: 'http://www.example.com', controller: this.controller }) //需要手动替换为真实网站
          .width('100%')
          .userAgent(this.userAgentPa)
          .onUrlLoadIntercept((event) => {
            let userAgent = this.controller.getUserAgent();
            this.userAgentPa = userAgent + ' 111111111'
            return false;
          })
      }
      .width('100%')
    }
    .height('100%')
  }
}

Web组件中如何通过手势滑动返回上一个Web页面(API 9)

解决措施

通过重写onBackPress函数来自定义返回逻辑,使用WebviewController判断是否返回上一个Web页面。

示例代码

import web_webview from '@ohos.web.webview';
@Entry
@Component
struct Index {
  controller: web_webview.WebviewController = new web_webview.WebviewController();
  build() {
    Column() {
      Web({ src: 'http://www.example.com', controller: this.controller })//需要手动替换为真实网站
    }
  }
  onBackPress() {
    // 当前页面是否可前进或者后退给定的step步(-1),正数代表前进,负数代表后退
    if (this.controller.accessStep(-1)) {
      this.controller.backward(); // 返回上一个web页
      // 执行用户自定义返回逻辑
      return true
    } else {
      // 执行系统默认返回逻辑,返回上一个page页
      return false
    }
  }
}

WebView支持同层渲染吗(API 10)

解决措施

  1. 支持Video、Map、Camera、Canvas、WebGL、WebView组件同层渲染。
  2. 支持将Web embed标签的id、type、src、width、height、url属性传递给原生组件。

WebView有哪些调试工具,调试工具的用法是什么(API 10)

解决措施

setWebDebuggingAccess()接口开启Web组件前端页面调试能力,利用DevTools工具可以在2in1上调试移动设备上的前端网页,设备需为4.1.0及以上版本。

WebView如何实现网络请求拦截功能(API 10)

解决措施

可以通过onInterceptRequest()接口实现自定义资源请求响应,该能力可用于自定义Web页面响应、自定义文件资源响应等场景。当Web网页发起资源加载请求时,应用层会收到该请求消息并构造本地资源响应消息发送给Web内核,Web内核根据应用层响应信息进行页面资源加载。

WebView和原生进行通信的方式有哪些,如何实现(API 10)

解决措施

  1. Native->H5使用runJavaScript接口注入JS进行通信,H5->Native使用registerJavaScriptProy接口。先将Native方法注册至H5侧,H5再通过调用前端方法实现与Native侧的通信。
  2. runJavaScript、registerJavaScriptProy接口同时在NDK侧C API暴露。
  3. 使用onInterceptrequest接口拦截H5侧请求,同时将Native侧数据作为Response返回至H5,实现Native与H5的通信。

WebView进程模型和渲染机制是什么(API 11)

解决措施

  1. 进程模型:1个主进程、多个render进程。
  2. 渲染机制:web自渲染。

系统目前是否支持Webrtc的功能?规格是什么?

解决措施

  1. WebView支持Webrtc的P-P功能以及音视频流功能。
  2. 非WebView场景,系统不直接提供Webrtc,但会提供技术支持,比如支持三方gn+ninja交叉编译方式适配Webrtc(RR-30030985),包含以下两点:
    • sdk支持gn+ninja交叉编译方式
    • 提供编译样例指导

Webview如何设置mixcontent策略,用以解决http与https混合加载的问题?

解决措施

Webview提供mixedMode(mixedMode: MixedMode)接口,设置是否允许加载超文本传输协议(HTTP)和超文本传输安全协议(HTTPS)混合内容,默认不允许加载HTTP和HTTPS混合内容。

WebView除了设置缓存,还有什么方式可以提升渲染速度吗?

解决措施

使用prepareForPageLoad接口开启预解析。

如何预创建Web组件?如何回收web组件复用?

解决措施

通过ArkUI提供的组件动态上下树能力,实现Web组件预创建、回收复用,使用指南见参考链接。

目前OpenHarmony是否有提供类似其他系统的JavaScript引擎能力?

解决措施

目前已支持。

了解到目前还有很多小伙伴不知道学习鸿蒙需要重点掌握哪些核心要领?


为了帮助大家更深入有效的学习到鸿蒙开发知识点,我特意给大家准备了一份全套最新版的HarmonyOS NEXT学习资源, 内容包含了:【ArkTS、ArkUI、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战】等技术知识点。

如果你是一名Android、Java、前端等开发人员、或是刚开始学习鸿蒙开发。想要转入鸿蒙方向发展。可以直接领取这份资料辅助你的学习。鸿蒙星河版学习路线+学习文档+面试题←点击领取,下面是鸿蒙开发的学习路线图。

应用开发中级就业技术

 应用开发中高级就业技术

南北双向高工技能基础

 全网首发-工业级 南向设备开发就业技术

HarmonyOS教学视频:语法ArkTS、TypeScript、ArkUI等.....视频教程

鸿蒙生态应用开发白皮书V2.0PDF

获取完整版白皮书方式请点击:鸿蒙生态应用开发白皮书V2.0PDF (qq.com)

以下也为大家准备了针对鸿蒙成长路线打造的鸿蒙学习文档。《鸿蒙开发学习手册》(共计890页)鸿蒙开发资料等…希望对大家有所帮助:

鸿蒙 (Harmony OS)开发学习手册

一、入门必看

  1. 应用开发导读(ArkTS)
  2. ……

二、HarmonyOS 概念

  1. 系统定义
  2. 技术架构
  3. 技术特性
  4. 系统安全
  5. ........

三、如何快速入门?

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

四、开发基础知识

  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. ……

更多了解更多鸿蒙开发的相关知识可以参考:鸿蒙星河版学习路线+学习文档+面试题

  • 12
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值