日本熟妇hd丰满老熟妇,中文字幕一区二区三区在线不卡 ,亚洲成片在线观看,免费女同在线一区二区

快速開始

更新時(shí)間:

本文介紹如何將 H5 容器組件接入到 HarmonyOS NEXT 客戶端。您可以基于已有工程使用 ohpmrc 方式接入 H5 容器 SDK 到客戶端。

前置條件

添加 H5 容器 SDK 之前,請您確保已經(jīng)將工程接入到 mPaaS。更多信息請參見 接入 mPaaS 能力

引入依賴

在項(xiàng)目的.ohpmrc文件中添加如下倉庫:

@mpaas:registry=https://mpaas-ohpm.oss-cn-hangzhou.aliyuncs.com/meta

添加 SDK

通過 使用 mppm 工具 安裝 H5 容器組件。

image

配置權(quán)限

module.json5 中配置所需權(quán)限。

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

使用 SDK

初始化

在 mPaaS 框架初始化完成之后,初始化 HRiver。代碼如下:

HRiver.init();

使用 SDK 之前必須初始化 mPaaS 框架,設(shè)置 userId 和 appsecret,其中 appsecret 從 AppCenter 后臺(tái)獲取,具體查看 獲取 HarmonyOS NEXT config 配置文件(beta)

代碼示例如下:

import AbilityStage from '@ohos.app.ability.AbilityStage';
import { MPFramework } from '@mpaas/framework';

export default class ModuleEntry extends AbilityStage {
  async onCreate() {
    MPFramework.create(this.context);
    
    MPFramework.instance.userId = 'MPTestCase'
    MPFramework.instance.appSecret = "12a711d78980f661aca5401788fdf09a";
  }
}

打開離線包

初始化 HRiver后調(diào)用 startApp 打開離線包。

import { HRiver } from '@mpaas/hriver'

/**
* 打開離線包
* @param appId: 離線包id
* @param startParams: 啟動(dòng)參數(shù),可以不傳。控制TitleBar、指定頁面等
*/
HRiver.startApp(appId: string, startParams?: Map<string, Object>)

代碼示例如下:

import { HRiver } from '@mpaas/hriver'

// 示例1:
HRiver.startApp('20190517') // 直接啟動(dòng)離線包

// 示例2: 
let startParams: Map<string, Object> = new Map();
startParams.set('defaultTitle', '默認(rèn)標(biāo)題') //加載階段顯示默認(rèn)標(biāo)題
HRiver.startApp('20190517', startParams)

打開在線頁面

初始化 HRiver 之后調(diào)用 startUrl 打開在線頁面。

import { HRiver } from '@mpaas/hriver'

/**
* 打開在線頁面
* @param url: 在線地址
* @param startParams: 啟動(dòng)參數(shù)。可以不傳,控制TitleBar、指定頁面等
*/
HRiver.startUrl(url: string, startParams: Map<string, Object>)

注冊自定義 JSAPI

初始化 HRiver 之后調(diào)用 registerPlugin 注冊自定義 JSAPI。

import { HRiver } from '@mpaas/hriver'

/**
* 注冊自定義 JSApi 實(shí)現(xiàn)
* @param pluginClass: pluginClass列表,如 registerPlugin({CustomPlugin1, CustomPlugin2}, HRiver.SCOPE_PAGE)
* @param scope: 可以不傳。默認(rèn)HRiver.SCOPE_PAGE。HRiver.SCOPE_APP表示離線包App級別生命周期;HRiver.SCOPE_PAGE表示頁面級別生命周期
*/
HRiver.registerPlugin(pluginClass: ESObject, scope: string)

代碼示例:

HRiver.registerPlugin({H5CustomPlugin, H5Custom1Plugin})

plugin 實(shí)現(xiàn)代碼示例如下:

import { HRiver, H5SimplePlugin, H5EventFilter, H5Event, H5BridgeContext } from '@mpaas/hriver'

class H5CustomPlugin extends H5SimplePlugin {
  onPrepare(filter: H5EventFilter): void {
    filter.addAction('myapi1')
  }

  handleEvent(event: H5Event, context: H5BridgeContext): Boolean {
    if ('myapi1' == event.action) {
      context.sendBridgeResult({
        success: true,
        data: 'myapi1調(diào)用成功'
      })
      return true
    }
    return super.handleEvent(event, context);
  }
}

class H5Custom1Plugin extends H5SimplePlugin {
  onPrepare(filter: H5EventFilter): void {
    filter.addAction('myapi2')
  }

  handleEvent(event: H5Event, context: H5BridgeContext): Boolean {
    if ('myapi2' == event.action) {
      context.sendBridgeResult({
        success: true,
        data: 'myapi2調(diào)用成功'
      })
      return true
    }
    return super.handleEvent(event, context);
  }
}

Native 調(diào)用 H5

Native 調(diào)用 H5 有以下兩種方法。

  • 在自定義 JSAPI 中通過 H5BridgeContext.sendToWeb 方法調(diào)用 H5。

    import { H5BridgeContext, H5Event, H5EventFilter, H5SimplePlugin, HRiver } from '@mpaas/hriver';
    class H5CustomPlugin extends H5SimplePlugin {
      handleEvent(event: H5Event, context: H5BridgeContext): Boolean {
        // native 調(diào)用 h5
        context.sendToWeb('customCallWeb', {
            data: 'abc'
        })
    
        ... // 其他代碼
      }
    }
  • 在 Native 代碼中獲取 TopAppactivityPage,獲得最新的頁面,通過頁面調(diào)用 sendToWeb 方法。

    import { HRiver,
      XRiverProxy,
      getProxy,
      AppManager,
      AppNode,
      Page
    } from '@mpaas/hriver';
    {
      let appManager = getProxy(XRiverProxy.AppManager) as AppManager
      let appNode: AppNode | null = appManager.findTopApp()
      if (appNode != null) {
        let page: Page | null = appNode.getActivePage()
        if (page != null) {
          page.sendToWeb('testAction', {data: ''})
        }
      }
    }

加載內(nèi)置離線包

加載所有內(nèi)置離線包,包括內(nèi)置的公共離線包。

初始化 HRiver 之后調(diào)用 loadOfflineResource 加載內(nèi)置離線包。

import { HRiver } from '@mpaas/hriver'

/**
* 加載內(nèi)置離線包
* @param jsonFileName: 內(nèi)置離線包的 h5_json.json 的文件名,放到rawfile目錄中。如:h5_json.json。
* @param callback: 格式 (result: string) => {}。內(nèi)置離線包加載完成回調(diào)的 Function
*/
HRiver.loadOfflineResource(jsonFileName: string, callback: Function)

代碼示例如下:

  1. entry/src/main/resources/rawfile 下添加 h5_json.json(文件從 Appcenter 后臺(tái)下載即可)。

    {
       "config":{
          "updateReqRate":16400,
          "limitReqRate":13600,
          "appPoolLimit":3,
          "versionRefreshRate":86400
       },
       "data":[
          {
             "app_desc":"離線包1",
             "app_id":"20180910",
             "auto_install":1,
             "fallback_base_url":"https://mcube-prod.oss-cn-hangzhou.aliyuncs.com/570DA89281533-default/20180910/1.0.0.3_all/nebula/fallback/",
             "global_pack_url":"",
             "icon_url":"",
             "installType":1,
             "main_url":"/www/index.html",
             "name":"離線包1",
             "online":1,
             "package_url":"https://mcube-prod.oss-cn-hangzhou.aliyuncs.com/570DA89281533-default/20180910/1.0.0.3_all/nebula/20180910_1.0.0.3.amr",
             "patch":"",
             "sub_url":"",
             "version":"1.0.0.3",
             "vhost":"https://20180910.h5app.com"
          },
            {
                "app_desc":"離線包2",
                "app_id":"20190517",
                "auto_install":1,
                "fallback_base_url":"https://mcube-prod.oss-cn-hangzhou.aliyuncs.com/570DA89281533-default/20190517/1.0.0.0_all/nebula/fallback/",
                "global_pack_url":"",
                "icon_url":"",
                "installType":1,
                "main_url":"/www/index.html",
                "name":"離線包2",
                "online":1,
                "package_url":"https://mcube-prod.oss-cn-hangzhou.aliyuncs.com/570DA89281533-default/20190517/1.0.0.0_all/nebula/20190517_1.0.0.0.amr",
                "patch":"",
                "sub_url":"",
                "version":"1.0.0.0",
                "vhost":"https://20190517.h5app.com"
            }
       ],
       "resultCode":100,
       "resultMsg":"操作成功",
       "state":"success"
    }
  2. 下載 amr 并命名為 ${appid}_${version}.amr

    image

  3. 調(diào)用 API。

    import { HRiver } from '@mpaas/hriver'
    
    HRiver.loadOfflineResource('h5_json.json', (result: string) => {
      this.resultText = this.resultText + `\n${result} 預(yù)加載成功`
    })

更新離線包

import { HRiver } from '@mpaas/hriver'

/**
 * 批量更新離線包
 * @param appIds: 需要更新離線包的appId列表
 * @param updateCallback: 格式必須 (result: boolean, code: number) => {}。更新接口返回后回調(diào)的Function
 */
HRiver.updateApp(appIds?: Array<string>, updateCallback?: Function)

/**
 * 更新所有離線包。
 * @param updateCallback: 格式必須 (result: boolean, code: number) => {}。更新接口返回后回調(diào)的Function
 */
HRiver.updateAll(updateCallback: Function)

/**
 * 批量更新離線包
 * @param appIds: 離線包的appId和version的map
 * @param updateCallback: 格式必須 (result: boolean, code: number) => {}。更新接口返回后回調(diào)的Function
 */
HRiver.updateAppWithVersion(appIds?: Map<string, string>, updateCallback?: Function)

代碼示例如下:

import { HRiver } from '@mpaas/hriver'

HRiver.updateApp(['90000002'], (result: boolean, code: number) => {
  this.resultText = `90000002更新結(jié)果: ${result}`
})

配置公共離線包

  1. 設(shè)置 H5CommonAppProvider

    import { HRiver, H5CommonAppProvider } from '@mpaas/hriver'
    
    /**
    * 配置公共離線包 Provider,必須在 HRiver.init() 之前調(diào)用
    */
    HRiver.setProvider(H5CommonAppProvider.name, new H5AppCommonProviderImpl())
    說明

    setProvider 必須在 HRiver.init() 之前調(diào)用。

  2. 實(shí)現(xiàn) H5AppCommonProviderImpl.etsgetCommonResourceAppList 方法。

    import { HRiver, H5CommonAppProvider } from '@mpaas/hriver'
    
    export class H5AppCommonProviderImpl extends H5CommonAppProvider {
      getCommonResourceAppList(): Array<string> {
        return ['20220719'] // 返回公共離線包id列表
      }
    }

支持 fallback 邏輯

保持和 iOS/Android 一致,離線包沒下載成功情況下優(yōu)先打開 fallback 在線地址。

該功能默認(rèn)關(guān)閉,可以通過以下開關(guān)打開:

實(shí)現(xiàn) H5CommonAppProvider 的 configJSON 方法,增加 enableFallback 參數(shù)。

export class H5AppCommonProviderImpl extends H5CommonAppProvider {
  ... // 其他配置

  // configJson,配置更新頻率等
  configJSON(): string {
    return JSON.stringify({
      enableFallback: 'YES',
      xxx // 其他配置
    })
  }
}

設(shè)置 UserAgent

import { HRiver } from '@mpaas/hriver'

HRiver.setUserAgent(userAgent)
說明

setUserAgentHRiver.init() 之后調(diào)用,會(huì)在默認(rèn) UserAgent 之后拼接設(shè)置的 useragent

設(shè)置離線包默認(rèn)更新頻率

  1. 設(shè)置 H5CommonAppProvider

    import { HRiver, H5CommonAppProvider } from '@mpaas/hriver'
    
    /**
    * 配置公共離線包Provider、離線包更新頻率等功能,必須在HRiver.init()之前調(diào)用
    */
    HRiver.setProvider(H5CommonAppProvider.name, new H5AppCommonProviderImpl())
    說明

    setProvider 必須在 HRiver.init() 之前調(diào)用。

  2. 實(shí)現(xiàn) H5CommonAppProviderconfigJSON 方法,代碼示例如下。

    import { HRiver, H5CommonAppProvider } from '@mpaas/hriver'
    
    export class H5AppCommonProviderImpl extends H5CommonAppProvider {
      ... // 其他配置
    
      // configJson,配置更新頻率等
      configJSON(): string {
        return JSON.stringify({
          h5_nbmngconfig: "{\"config\":{\"al\":\"3\",\"pr\":{\"4\":\"86400\",\"common\":\"864000\"},\"ur\":\"1\",\"fpr\":{\"common\":\"3888000\"}},\"switch\":\"yes\"}"
        })
      }
    }

    具體參數(shù)如下:

    h5_nbmngconfig: "{\"config\":{\"al\":\"3\",\"pr\":{\"4\":\"86400\",\"common\":\"864000\"},\"ur\":\"1800\",\"fpr\":{\"common\":\"3888000\"}},\"switch\":\"yes\"}"

    其中的 ur: 1800 表示更新頻率為 1800 秒,使用時(shí)修改 ur 的值即可。

配置離線包簽名校驗(yàn)

  1. 設(shè)置 H5CommonAppProvider

    import { HRiver, H5CommonAppProvider } from '@mpaas/hriver'
    
    /**
    * 配置公共離線包Provider、離線包更新頻率、簽名校驗(yàn)等功能,必須在HRiver.init()之前調(diào)用
    */
    HRiver.setProvider(H5CommonAppProvider.name, new H5AppCommonProviderImpl())
    說明

    setProvider 必須在 HRiver.init() 之前調(diào)用。

  2. 實(shí)現(xiàn) H5CommonAppProvidershouldVerifypubKey 方法,代碼示例如下:

    import { HRiver, H5CommonAppProvider } from '@mpaas/hriver'
    
    export class H5AppCommonProviderImpl extends H5CommonAppProvider {
     ... // 其他配置 
    
     /**
     * 是否開啟離線包校驗(yàn),默認(rèn)關(guān)閉
     * return: true表示開啟,false表示關(guān)閉
     */
     shouldVerify(): boolean {
     return false
     }
    
     // 離線包校驗(yàn)的公鑰,如果shouldVerify為false 則無需設(shè)置,否則必須設(shè)置公鑰
     pubKey(): string {
     return ''
     }
    }

開啟調(diào)試模式

HRiver.enableDebug(true)

監(jiān)聽頁面生命周期

初始化完成后設(shè)置 provider。

import {H5PageLifeCycleProvider} from '@mpaas/hriver';
  
HRiver.setProvider(H5PageLifeCycleProvider.name, new H5PageLifeCycle())

H5PageLifeCycle

import { H5PageLifeCycleProvider, Page } from '@mpaas/hriver';
import { hilog } from '@kit.PerformanceAnalysisKit';

export class H5PageLifeCycle extends H5PageLifeCycleProvider {
  onPageShow(routerName: string, page?: Page | undefined): void {
    super.onPageShow(routerName, page);
    hilog.debug(1, 'H5PageLifeCycle', "pageshow: " + page?.pageUrl)
  }

  onPageHide(routerName: string, page?: Page | undefined): void {
    super.onPageHide(routerName, page);
    hilog.debug(1, 'H5PageLifeCycle', "onPageHide: " + page?.pageUrl)
  }

  onPageCreate(page?: Page | undefined): void {
    super.onPageCreate(page);
    hilog.debug(1, 'H5PageLifeCycle', "onPageCreate: " + page?.pageUrl)
  }

  onPageExit(page?: Page | undefined): void {
    super.onPageExit(page);
    hilog.debug(1, 'H5PageLifeCycle', "onPageExit: " + page?.pageUrl)
  }

  onBackPress(page?: Page | undefined): boolean {
    hilog.debug(1, 'H5PageLifeCycle', "onBackPress: " + page?.pageUrl)
    return super.onBackPress(page);

  }
}

支持注銷 Plugin

通過 Page 的 Page.ets 實(shí)現(xiàn)注銷。

// 根據(jù)action注銷
unregisterPluginByAction(action: string);

// 根據(jù)pluginName注銷
unregisterPluginByPluginName(name: string);

示例如下:

image

支持頁面嵌入模式

頁面嵌入模式基于 Navigation 實(shí)現(xiàn)。

  1. 創(chuàng)建離線包需要的 NavPathStack。

    pageInfos: NavPathStack = new NavPathStack()
  2. 在頁面需要嵌入的位置添加空白組件,以下為示例:

    重要

    mode 必須使用 NavigationMode.Stack,否則橫豎屏/折疊屏切換有問題。

    Navigation(this.pageInfos) {
              Column() {
                // 空白頁面用于嵌入離線包頁面, 不用填任何內(nèi)容
              }.width('100%') // 寬度根據(jù)需要
              .backgroundColor(Color.Red) // 只是示例
              .height(500)  // 高度根據(jù)實(shí)際
            }.navDestination(this.PagesMap)
            .mode(NavigationMode.Stack)
    
    
    // pagesMap實(shí)現(xiàn):
    import {HRBuilder, RouterUtils, HRiver, H5RouterNavStackProvider} from '@mpaas/hriver'
    
    let mPaaSHRiverBuilder: WrappedBuilder<[string, ESObject]> = wrapBuilder(HRBuilder);
    
    @Builder
    PagesMap(name: string, params: ESObject) {
      if (RouterUtils.isMPHRiverPage(name)) {
        mPaaSHRiverBuilder.builder(name, params)
      } else if (name == 'xxx') {
        // 其他業(yè)務(wù)的頁面
      }
    }
  3. 啟動(dòng)離線包和在線頁面時(shí),需要添加第三個(gè)參數(shù)并傳入步驟 1 中創(chuàng)建的 NavPathStack,增加 embedPage 參數(shù)用來表示內(nèi)嵌頁面。

    let param: Map<string, Object> = new Map<string, Object>()
    param.set('embedPage', 'YES')
    HRiver.startUrl('https://www.baidu.com', param, this.pageInfos)
    // HRiver.startApp('90000000', param, this.pageInfos)
  4. 添加返回事件攔截。

    HRiver.setProvider(H5PageLifeCycleProvider.name, new H5PageLifeCycle())

    import { H5PageLifeCycleProvider, Page } from '@mpaas/hriver';
    import { hilog } from '@kit.PerformanceAnalysisKit';
    import { router } from '@kit.ArkUI';
    
    export class H5PageLifeCycle extends H5PageLifeCycleProvider {
    
      onPageShow(routerName: string, page?: Page | undefined): void {
        super.onPageShow(routerName, page);
        hilog.debug(1, 'H5PageLifeCycle', "onPageShow: " + page?.pageUrl)
    
      }
      onPageHide(routerName: string, page?: Page | undefined): void {
    
        super.onPageHide(routerName, page);
        hilog.debug(1, 'H5PageLifeCycle', "onPageHide: " + page?.pageUrl)
      }
      onPageCreate(page?: Page | undefined): void {
    
        super.onPageCreate(page);
        hilog.debug(1, 'H5PageLifeCycle', "onPageCreate: " + page?.pageUrl)
      }
      onPageExit(page?: Page | undefined): void {
    
        super.onPageExit(page);
        hilog.debug(1, 'H5PageLifeCycle', "onPageExit: " + page?.pageUrl)
      }
      onBackPress(page?: Page | undefined): boolean {
        hilog.debug(1, 'H5PageLifeCycle', "onBackPress: " + page?.pageUrl)
        let navPathStack: NavPathStack|undefined = page?.getSession()?.getRouter()?.getNavPathStack()
        if (navPathStack && page && page.embedPage && navPathStack.size() == 1) {
          router.back()
          return true;
        }
        return super.onBackPress(page);
      }
    }

UI 定制

自定義導(dǎo)航欄

  1. 初始化完成后通過 provider 設(shè)置自定義導(dǎo)航欄。

    import {HRBuilder, RouterUtils, HRiver, H5CommonAppProvider, H5RouterNavStackProvider,
      CustomUIBuilderProvider,
      H5CacheProvider
    } from '@mpaas/hriver'
    
    HRiver.setProvider(CustomUIBuilderProvider.name, new CustomUIBuilderProviderImpl())
  2. 實(shí)現(xiàn) CustomUIBuilderProviderImpl

    import { CustomUIBuilderProvider, Page } from '@mpaas/hriver';
    import { CustomUIBuilder } from '../pages/CustomTitleBarComponent';
    
    export class CustomUIBuilderProviderImpl extends CustomUIBuilderProvider {
      getCustomUIBuilder(): WrappedBuilder<[string, Page]> {
        return wrapBuilder(CustomUIBuilder);
      }
    }

    其中 CustomUIBuilder 為業(yè)務(wù)自定義 titlebar 組件的全局 Builder。實(shí)現(xiàn)參考如下:

    /**
    *  name: 自定義組件的名稱
    *  page: 自定義titlebar對應(yīng)的頁面Page
    */
    @Builder
    export function CustomUIBuilder(name: string, p: Page) {
      if (name === 'titleBar') {
        CustomTitleBarComponent({page: p, titleBarData: p.titleBarData})
      }
    }

    CustomTitleBarComponent 為具體的標(biāo)題組件,titleBarData 為標(biāo)題欄所需要的數(shù)據(jù),數(shù)據(jù)發(fā)生變化會(huì)實(shí)時(shí)刷新。示例參考如下:

    import { H5NavMenuItemData, HRiverUtil, Page, TitleBarData } from '@mpaas/hriver'
    
    const TAG: string = "CustomTitleBarComponent"
    
    
    const MENU_MARGIN: number = 5
    const DEFAULT_MARGIN: number = 12
    
    @Builder
    export function CustomUIBuilder(name: string, p: Page) {
      if (name === 'titleBar') {
        CustomTitleBarComponent({page: p, titleBarData: p.titleBarData})
      }
    }
    
    @Component
    export struct CustomTitleBarComponent {
      page: Page | null = null
      @Prop titleBarData: TitleBarData
    
      aboutToAppear(): void {
      }
    
      build() {
        RelativeContainer() {
          Button() {
            Image(this.getBackIconImage())
              .id('titlebar_back_img')
              .width(12)
              .height(20)
          }
          .width(48)
          .height('100%')
          .borderRadius(0)
          .backgroundColor(Color.Transparent)
          .align(Alignment.Center)
          .alignRules({
            top: { anchor: '__container__', align: VerticalAlign.Top }
          })
          .id("h5_nav_close")
          .onClick((event) => {
            if (this.page != null) {
              this.page.backClickEvent()
            }
          })
    
          Flex({ justifyContent: FlexAlign.Center, direction: FlexDirection.Column }) {
            //如果設(shè)置了圖片標(biāo)題就只顯示圖片
            if (this.titleBarData.titleImage) {
              Image(this.titleBarData.titleImage)
                .id('titlebar_title_image')
                .height(36).onClick(() => {
                this.onTitleClick()
              })
            } else {
              Flex({ justifyContent: FlexAlign.Start,direction: FlexDirection.Row }){
                Text(this.titleBarData.title)
                  .fontSize(18)
                  .textAlign(TextAlign.Start)
                  .textOverflow({ overflow: TextOverflow.Ellipsis })
                  .maxLines(1)
                  .fontColor(this.titleBarData.titleColor)
                  .onClick(() => {
                    this.onTitleClick()
                  })
                if(this.titleBarData.showTitleLoading ){
    
                  Image(this.getTitleBarLoadingIcon()).width(18).height(18)
                    .id('titlebar_progress_img')
                    .margin({left:5,top:1})
                    .rotate({ angle: this.titleBarData.loadingRotateAngle })
                    .animation({
                      duration:3000,
                      curve: Curve.Linear,
                      delay: 0,
                      iterations: -1,
                      playMode: PlayMode.Normal,
                    }).onAppear(()=>{
                    this.titleBarData.loadingRotateAngle = 360
                  })
    
                }
    
              }
    
              if (this.titleBarData.subtitle) {
                Text(this.titleBarData.subtitle)
                  .textAlign(TextAlign.Start)
                  .fontColor(this.titleBarData.titleColor)
                  .textOverflow({ overflow: TextOverflow.Ellipsis })
                  .maxLines(1)
                  .fontSize(18)
                  .onClick(() => {
                    this.onTitleSubtitleClick()
                  })
              }
            }
    
          }.id("h5_tv_title")
          .height("100%")
          .alignRules({
            top: { anchor: '__container__', align: VerticalAlign.Top },
            left: { anchor: 'h5_nav_close', align: HorizontalAlign.End },
            right: { anchor: "h5_nav_options", align: HorizontalAlign.Start }
          })
    
          if (this.titleBarData.optionMenuState) {
            if (this.titleBarData.menuType == TitleBarData.MENU_TYPE_TITLE) {
              Text(this.titleBarData.menuTitle)
                .fontSize(16)
                .align(Alignment.Center)
                .textAlign(TextAlign.Center)
                .fontColor(this.titleBarData.menuColor)
                .height('100%')
                .id("h5_nav_options")
                .alignRules({
                  top: { anchor: '__container__', align: VerticalAlign.Top },
                  right: { anchor: '__container__', align: HorizontalAlign.End }
                })
                .onClick(() => {
                  this.onMoreClick(false, 0)
                })
                .margin({
                  right: DEFAULT_MARGIN
                })
            } else if (this.titleBarData.menuType == TitleBarData.MENU_TYPE_ICON) {
              Button() {
                Image(HRiverUtil.getIconImage(this.titleBarData.menuIcon))
                  .id('titlebar_right_icon')
                  .width(22)
                  .height(22)
                  .objectFit(ImageFit.Contain)
              }
              .width(30)
              .borderRadius(0)
              .backgroundColor(Color.Transparent)
              .align(Alignment.Center)
              .id("h5_nav_options")
              .height("100%")
              .onClick(() => {
                this.onMoreClick(false, 0)
              })
              .alignRules({
                top: { anchor: '__container__', align: VerticalAlign.Top },
                right: { anchor: '__container__', align: HorizontalAlign.End }
              })
              .margin({
                right: DEFAULT_MARGIN
              })
            } else if (this.titleBarData.menuType == TitleBarData.MENU_TYPE_MORE) {
              Button() {
                Image(HRiverUtil.getIconImage('more'))
                  .id('titlebar_right_more')
                  .width(22)
                  .height(22)
                  .objectFit(ImageFit.Contain)
              }
              .width(48)
              .borderRadius(0)
              .backgroundColor(Color.Transparent)
              .align(Alignment.Center)
              .id("h5_nav_options")
              .height("100%")
              .margin({
                right: DEFAULT_MARGIN
              })
              .alignRules({
                top: { anchor: '__container__', align: VerticalAlign.Top },
                right: { anchor: '__container__', align: HorizontalAlign.End }
              }).onClick(() => {
                if (!this.titleBarData.preventDefault) {
                  this.titleBarData.customPopup = !this.titleBarData.customPopup
                }
    
                this.onMoreClick(true, 0)
              })
              .bindPopup(this.titleBarData.customPopup , {
                builder: this.MenuBuilder,
                placement:Placement.BottomLeft,
                popupColor:"#fff",
                onStateChange: (e) => {
                  console.info(JSON.stringify(e.isVisible))
                  if (!e.isVisible) {
                    this.titleBarData.customPopup = false
                  }
                }
              })
            }
    
            if (this.titleBarData.menuType1 == TitleBarData.MENU_TYPE_TITLE) {
              Text(this.titleBarData.menuTitle1)
                .fontSize(16)
                .align(Alignment.Center)
                .textAlign(TextAlign.Center)
                .fontColor(this.titleBarData.menuColor1)
                .height('100%')
                .id("h5_nav_options1")
                .alignRules({
                  top: { anchor: '__container__', align: VerticalAlign.Top },
                  right: { anchor: 'h5_nav_options', align: HorizontalAlign.Start }
                })
                .margin({
                  right: MENU_MARGIN
                })
                .onClick(()=> {
                  this.onMoreClick(false, 1)
                })
            } else if (this.titleBarData.menuType1 == TitleBarData.MENU_TYPE_ICON) {
              Button() {
                Image(HRiverUtil.getIconImage(this.titleBarData.menuIcon1))
                  .id('titlebar_right_icon1')
                  .width(22)
                  .height(22)
                  .objectFit(ImageFit.Contain)
              }
              .width(30)
              .borderRadius(0)
              .backgroundColor(Color.Transparent)
              .align(Alignment.Center)
              .id("h5_nav_options1")
              .height("100%")
              .onClick(()=> {
                this.onMoreClick(false, 1)
              })
              .alignRules({
                top: { anchor: '__container__', align: VerticalAlign.Top },
                right: { anchor: 'h5_nav_options', align: HorizontalAlign.Start }
              })
              .margin({
                right: MENU_MARGIN
              })
            } else if (this.titleBarData.menuType1 == TitleBarData.MENU_TYPE_MORE) {
              Button() {
                Image(HRiverUtil.getIconImage('more'))
                  .id('titlebar_right_more1')
                  .width(22)
                  .height(22)
                  .objectFit(ImageFit.Contain)
              }
              .width(48)
              .borderRadius(0)
              .backgroundColor(Color.Transparent)
              .align(Alignment.Center)
              .id("h5_nav_options1")
              .height("100%")
              .margin({
                right: MENU_MARGIN
              })
              .alignRules({
                top: { anchor: '__container__', align: VerticalAlign.Top },
                right: { anchor: 'h5_nav_options', align: HorizontalAlign.Start }
              }).onClick(() => {
                if (!this.titleBarData.preventDefault) {
                  this.titleBarData.customPopup1 = !this.titleBarData.customPopup1
                }
    
                this.onMoreClick(true, 1)
              })
              .bindPopup(this.titleBarData.customPopup1 , {
                builder: this.MenuBuilder,
                placement:Placement.BottomLeft,
                popupColor:"#fff",
                onStateChange: (e) => {
                  console.info(JSON.stringify(e.isVisible))
                  if (!e.isVisible) {
                    this.titleBarData.customPopup1 = false
                  }
                }
              })
            }
    
          }
    
    
    
        }.height(this.titleBarData.showTitleBar ? 48 : 0)
      }
    
      getTitleBarLoadingIcon(): Resource | string {
        return $rawfile(`icon/h5_title_bar_progress_bg.webp`)
      }
    
      getIconImage(icon: string): Resource | string {
        return HRiverUtil.getIconImage(icon)
      }
    
      getBackIconImage(): Resource | string {
        return $rawfile(`icon/hriverback.webp`)
      }
    
      onTitleClick() {
        if (this.page != null) {
          this.page.titleBarClickEvent()
        }
    
      }
    
      onTitleSubtitleClick() {
        if (this.page != null) {
          this.page.subTitleBarClickEvent()
        }
    
      }
    
      onMoreClick(fromMenu:boolean, index: number) {
    
        if (this.page != null) {
          this.page.onMoreClick(fromMenu, index)
        }
    
      }
      onMoreItemClick(tag: string, name: string,isShowPopMenu:boolean) {
        if (this.page != null) {
          this.page.onMoreItemClick(tag, name, isShowPopMenu)
        }
    
      }
    
      @Builder
      MenuBuilder() {
        Flex({ direction: FlexDirection.Column, justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
          ForEach(this.titleBarData.h5NavMenuItemList, (item: H5NavMenuItemData, index) => {
            Column() {
              Row() {
                Image(item.icon).width(20).height(20).margin({ right: 5 })
                Text(item.name).fontSize(16)
              }
              .width('100%')
              .height(30)
              .padding({ left: 10 })
              .justifyContent(FlexAlign.Start)
              .align(Alignment.Center)
              .onClick(() => {
                if (item) {
                  this.onMoreItemClick(item.tag || '', item.name || '',false)
                  this.titleBarData.customPopup = false
                  this.titleBarData.customPopup1 = false
                }
    
              })
    
              if (index != this.titleBarData.h5NavMenuItemList.length - 1) {
                Divider().height(10).width('90%').color('#ccc')
              }
            }.padding(5).height(40)
          })
        }.width(150).height(165).backgroundColor("#fff")
    
      }
    
    }

自定義離線包加載頁/錯(cuò)誤頁

  1. 初始化完成之后設(shè)置 Provider。

    import {
      CustomLoadingBuilderProvider} from '@mpaas/hriver';
      
    HRiver.setProvider(CustomLoadingBuilderProvider.name,  new CustomLoadingBuilderProviderImpl())
    
  2. 實(shí)現(xiàn) CustomLoadingBuilderProviderImpl 類。

    import { CustomLoadingBuilderProvider, H5Router, HRLoadingData } from '@mpaas/hriver';
    import { CustomUIBuilder } from './CustomLoadingComponent';
    
    export class CustomLoadingBuilderProviderImpl extends CustomLoadingBuilderProvider {
      getCustomUIBuilder(): WrappedBuilder<[string, HRLoadingData, H5Router]> {
        return wrapBuilder(CustomUIBuilder);
      }
    }
  3. 實(shí)現(xiàn) CustomLoadingComponent.ets 類,其中通過 loadingStatus 控制加載狀態(tài)。

    import { H5Router, HRLoadingData, LoadingStatus } from '@mpaas/hriver'
    
    const TAG: string = "CustomLoadingComponent"
    
    
    export const Loading_STATE_Init = 0
    export const Loading_STATE_Start = 1
    export const Loading_STATE_End = 2
    export const Loading_STATE_Err = 3
    @Builder
    export function CustomUIBuilder(name: string, loadingData: HRLoadingData, h5Router: H5Router) {
      if (name === 'loading') {
        CustomLoadingComponent({loadingStatus: loadingData.loadingStatus, h5Router: h5Router})
      }
    }
    
    @Component
    export struct CustomLoadingComponent {
      @ObjectLink loadingStatus: LoadingStatus
      h5Router?: H5Router
    
      aboutToAppear(): void {
      }
    
      build() {
        Row() {
          Column() {
            Flex({ direction: FlexDirection.Row }) {
              //返回按鈕
              Button() {
                Image($rawfile("icon/hriverback.webp"))
                  .width(12)
                  .height(20)
              }
              .width(48)
              .height('100%')
              .borderRadius(0)
              .backgroundColor(Color.Transparent)
              .align(Alignment.Center)
              .onClick((event) => {
                this.h5Router?.routerBack()
              })
    
            }.width('100%')
            .height(48)
            Image(this.loadingStatus.icon ? this.loadingStatus.icon : $rawfile("icon/hriverloading.webp"))
              .width(40)
              .height(40)
              .margin({top: 38})
            if (this.loadingStatus.state == Loading_STATE_Err ||
              this.loadingStatus.state == Loading_STATE_Start){
              Text(this.loadingStatus.state == Loading_STATE_Err ? `網(wǎng)絡(luò)不給力,請稍后再試 \n(${this.loadingStatus.code} ${this.loadingStatus.msg})` : this.loadingStatus.title)
                .fontSize(18)
                .margin({top: 15})
                .textAlign(TextAlign.Center)
            }
    
          }
          .width('100%')
          .margin({
            top: 48
          })
        }
      }
    
    
    }

自定義在線 URL 加載失敗的錯(cuò)誤頁

  1. 設(shè)置 Provider 攔截網(wǎng)頁錯(cuò)誤回調(diào)。

    HRiver.setProvider(H5WebClientProvider.name, new H5WebClientProviderImpl());
  2. H5WebClientProviderImpl 中實(shí)現(xiàn) onErrorReceive 方法。

    import { MPFramework } from '@mpaas/framework';
    import {  H5WebClientProvider, Page } from '@mpaas/hriver';
    import { util } from '@kit.ArkTS';
    
    export class H5WebClientProviderImpl  extends H5WebClientProvider{
    
      onErrorReceive(page: Page | undefined, request: WebResourceRequest | undefined, err: WebResourceError | undefined): boolean {
        let errorUrl = request?.getRequestUrl()
        let errorCode = err?.getErrorCode()
    
        if (errorCode == 403 || errorCode == 404) {
          // keep same with ios,not show errorPage for 404 and 403
          // log(TAG, "ignoreErrorPage 404 or 403, return ");
          return true;
        }
        let lastUrl = page?.webcontroller?.getUrl()
    
        if (errorUrl == page?.pageUrl || errorUrl == `${page?.pageUrl}/`) {
          // 從rawfile中讀取自定義錯(cuò)誤頁面demo_custom_err.html
          
          let dataBytes = MPFramework.instance.context.resourceManager.getRawFileContentSync('demo_custom_err.html')
          let textDecoder = new util.TextDecoder("utf-8", { fatal: false, ignoreBOM: false })
          let html = textDecoder.decodeWithStream(new Uint8Array(dataBytes), { stream: true })
    
          page?.webcontroller?.loadData(html, "text/html", "utf-8", lastUrl)
          return true;
        }
        return false
      }
    }
  3. demo_custom_err.html 文件中編寫錯(cuò)誤頁代碼。

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="UTF-8">
        <meta name="apple-mobile-web-app-capable" content="yes"/>
        <meta name="apple-mobile-web-app-status-bar-style" content="black"/>
        <meta name="format-detection" content="telephone=no"/>
        <meta name="format-detection" content="email=no"/>
        <meta name="viewport"
              content="width=device-width,initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=0"/>
        <title>!!!!</title>
        <style type="text/css">
            body {
            background-color: #FFF;
            }
    
            .am-page-result {
            text-align: center;
            }
    
            .am-page-result .am-page-result-pic {
            width: 135px;
            height: 135px;
            margin: 40px auto;
            }
    
            .am-page-result .am-page-result-pic img {
            width: 100%;
            height: 100%;
            }
    
            .am-page-result p {
            margin: 0;
            font-size: 16px;
            color: #999;
            }
    
            .am-page-result-button {
            margin-top: 25px;
            display: -webkit-box;
            display: -webkit-flex;
            display: flex;
            }
    
            .am-button {
            display: block;
            margin: 0 10px;
            padding: 0 10px;
            height: 42px;
            text-align: center;
            font-size: 18px;
            line-height: 42px;
            border-radius: 4px;
            outline: 0;
            -webkit-appearance: none;
            -webkit-box-flex: 1;
            -webkit-flex: 1;
            flex: 1;
            width: 50%;
            }
    
            .am-button[am-mode~=white] {
            border: 1px solid #DDD;
            color: #666;
            background-color: #FFF;
            }
    
            .am-button[am-mode~=white]:active {
            border-color: #D8D8D8;
            background-color: #F8F8F8;
            }
    
            .am-button[am-mode~=blue] {
            border: 1px solid #28F;
            color: #FFF;
            background-color: #39F;
            }
    
            .am-button[am-mode~=blue]:active {
            border-color: #17F;
            background-color: #28F;
            }
    
            .am-button[am-mode~=light], .am-button[am-mode~=light]:active {
            border: none;
            color: #39F;
            background-color: #FFF;
            }
    
            @media screen and (min-device-width: 375px) {
            .am-page-result .am-page-result-pic {
            width: 160px;
            height: 160px;
            margin: 45px auto;
            }
    
            .am-page-result-button {
            margin-top: 30px;
            }
    
            .am-button {
            margin: 0 20px;
            height: 44px;
            line-height: 44px;
            }
            }
    
            @media screen and (min-device-width: 414px) {
            .am-page-result .am-page-result-pic {
            width: 180px;
            height: 180px;
            margin: 50px auto;
            }
    
            .am-button {
            margin: 0 24px;
            height: 50px;
            line-height: 50px;
            }
            }
        </style>
    <body>
    <div class="am-page-result">
        <div class="am-page-result-pic">
            <img src="data:image/png;base64,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"/>
        </div>
        <p>這是自定義錯(cuò)誤頁面</p>
    
    </div>
    </body>
    <script>
    
    
    
    
    </script>
    </html>
    

設(shè)置和原生 View 一起滾動(dòng)

//在啟動(dòng)參數(shù)里添加
// scrollForward: 0: SELF_ONLY, 1: SELF_FIRST, 2: PARENT_FIRST, 3 : PARALLEL
// scrollBackward: 0: SELF_ONLY, 1: SELF_FIRST, 2: PARENT_FIRST, 3 : PARALLEL
param.set("scrollForward", 2)
param.set("scrollBackward", 1)

支持限制 Web 組件寬度

  • 通過啟動(dòng)參數(shù)控制。

    params.set('webWidth', xxx)。 // 參數(shù)支持string ('100%'百分比方式) 或者number (例如800表示800px)
  • 動(dòng)態(tài)控制。

    page.setWebWidth(webWidth: string | number)

鴻蒙 Web 行為定制

H5WebClientProvider

可以通過實(shí)現(xiàn) H5WebClientProvider 修改鴻蒙 H5 容器 Web 的一些默認(rèn)行為 API 。

HRiver.setProvider(H5WebClientProvider.name, new H5WebClientProviderImpl())

可定制的 API 如下:

export class H5WebClientProvider {

  // 頁面http錯(cuò)誤回調(diào)
  onHttpErrorReceive(page: Page | undefined, request: WebResourceRequest | undefined, response: WebResourceResponse | undefined) {
  }

  // 頁面下載回調(diào)
  onDownloadStart(page: Page | undefined, url: string | undefined, userAgent: string | undefined, contentDisposition: string | undefined,
    mimetype: string | undefined, contentLength: number | undefined) {
  }

  // 頁面ssl錯(cuò)誤回調(diào)
  onSslErrorEventReceive(page: Page | undefined, handler: SslErrorHandler, error: SslError) {

  }

  // 頁面錯(cuò)誤回調(diào)
  onErrorReceive(page: Page | undefined, request: WebResourceRequest | undefined, error: WebResourceError | undefined): boolean {
    return false
  }

  // 全屏回調(diào)
  onFullScreenEnter(page: Page | undefined, handler: FullScreenExitHandler) {

  }
 
  // 退出全屏回調(diào)
  onFullScreenExit(page: Page | undefined) {

  }

  // web權(quán)限申請回調(diào)
  onPermissionRequest(page: Page | undefined, request: PermissionRequest | undefined) {

  }

  // web screencapturerequest回調(diào)
  onScreenCaptureRequest(page: Page | undefined, handler: ScreenCaptureHandler | undefined) {

  }

  onPageBegin(page: Page | undefined, url: string | undefined) {

  }

  onAppear(page: Page | undefined) {

  }

  // web scroll回調(diào)
  onScroll(x: number, y: number, page: Page | undefined) {

  }

  getWindow(context: Context, page: Page | undefined): Promise<window.Window> | undefined {
    return undefined
  }

  // web 長按菜單
  onContextMenuShow(param: WebContextMenuParam | undefined, result: WebContextMenuResult | undefined) {
    return false
  }

  // web 文件選擇回調(diào)
  onShowFileSelector(fileSelector: FileSelectorParam, result: FileSelectorResult, page: Page | undefined) {
    return false
  }

  // web 定位相關(guān)回調(diào)
  onGeolocationShow(origin: string | undefined, geoLocation: JsGeolocation | undefined, page: Page | undefined) {

  }

  // web 定位相關(guān)回調(diào)
  onGeolocationHide(page: Page | undefined) {

  }
}

H5MixModeSettingProvider

可以通過 H5MixModeSettingProvider 設(shè)置 Web 支持 HTTP/HTTPS 的 MixedMode,具體使用如下:

HRiver.setProvider(H5MixModeSettingProvider.name, new H5MixModeSettingProviderImpl()) // 業(yè)務(wù)實(shí)現(xiàn)H5MixModeSettingProviderImpl
export class H5MixModeSettingProviderImpl extends H5MixModeSettingProvider {
  mixMode(page: Page | undefined): MixedMode {
      // 根據(jù)業(yè)務(wù)實(shí)際情況返回對應(yīng)的MixedMode
    return MixedMode.Compatible
  }
}
重要

鴻蒙系統(tǒng)不支持在 HTTPS 頁面加載地址為 HTTP 的 IP 鏈接,要么加載 HTTPS 的 IP 的鏈接,要么加載 HTTP 的非 IP 鏈接。

頁面路由支持 Navigation

默認(rèn)頁面路由使用 router 方式,鴻蒙 router 方式不支持關(guān)閉棧中某個(gè)頁面,只能一級級回退。離線包支持 Navigation 模式:

  1. 支持關(guān)閉棧中頁面

  2. 支持分欄模式

全局 Navigation 模式

  1. HRiver 初始化完成后,在啟動(dòng)離線包之前,需設(shè)置 H5RouterNavStackProvider

    HRiver.setProvider(H5RouterNavStackProvider.name, new NavStackProvider(this.pageInfos))
    import { H5RouterNavStackProvider } from '@mpaas/hriver';
    
    export class NavStackProvider extends H5RouterNavStackProvider {
      navStack: NavPathStack // 全局的navPathStack棧
    
      constructor(navStack: NavPathStack) {
        super();
        this.navStack = navStack;
      }
    
      getNavPathStack(): NavPathStack {
        return this.navStack
      }
    }
  2. navDestination 中配置 builderbuilder 中加載 mPaaS 全局 Builder。

    import {HRBuilder, RouterUtils, HRiver, H5RouterNavStackProvider} from '@mpaas/hriver'
    
    let mPaaSHRiverBuilder: WrappedBuilder<[string, ESObject]> = wrapBuilder(HRBuilder);
    
    @Builder
    PagesMap(name: string, params: ESObject) {
      if (RouterUtils.isMPHRiverPage(name)) {
        mPaaSHRiverBuilder.builder(name, params)
      } else if (name == 'xxx') {
        // 其他業(yè)務(wù)的頁面
      }
    }
    
    build() {
        Navigation(this.pageInfos) {
          Row() {
            Column() {
              // 業(yè)務(wù)頁面
              MainPage()
            }
            .width('100%')
          }
        }.navDestination(this.PagesMap)
      }

離線包獨(dú)立使用 Navigation 模式

  1. HRiver.startApp/HRiver.startUrl 的第三個(gè)參數(shù)傳入 NavPathStack 即可。

  2. 參考 全局 Navigation 模式 中的步驟 2。