HarmonyOS:使用ArkWeb构建页面

打印 上一主题 下一主题

主题 1017|帖子 1017|积分 3051

一、简介

   


    页面加载是Web组件的基本功能。根据页面加载数据泉源可以分为三种常用场景,包罗加载网络页面、加载本地页面、加载HTML格式的富文本数据。

页面加载过程中,若涉及网络资源获取,必要设置ohos.permission.INTERNET网络访问权限。
  二、加载网络页面

   开发者可以在Web组件创建时,指定默认加载的网络页面 。在默认页面加载完成后,如果开发者必要变更此Web组件体现的网络页面,可以通过调用loadUrl()接口加载指定的网页。Web组件的第一个参数变量src不能通过状态变量(比方:@State)动态更改地址,如需更改,请通过loadUrl()重新加载。

在下面的示例中,在Web组件加载完“https://www.baidu.com/”页面后,开发者可通过loadUrl接口将此Web组件体现页面变更为“https://www.baidu.com/xxx”。

    提醒:
起首必要在products/default/src/main/module.json5文件中先设置好允许步伐打开网络套接字,即申请权限ohos.permission.INTERNET。

  1. "requestPermissions": [
  2.       {
  3.         "name": "ohos.permission.INTERNET",
  4.         "reason": "$string:apply_for_network"
  5.       }
  6.     ],
复制代码
  

  1. {
  2.       "name": "apply_for_network",
  3.       "value": "允许应用使用网络"
  4. }
复制代码
  

  示例代码
  1. import { webview } from '@kit.ArkWeb'
  2. import { BusinessError } from '@kit.BasicServicesKit';
  3. @Entry
  4. @Component
  5. struct WebComponent {
  6.   controller: webview.WebviewController = new webview.WebviewController()
  7.   build() {
  8.     Column() {
  9.       Button('loadUrl').onClick(() => {
  10.         try {
  11.           // 点击按钮时,通过loadUrl,跳转到 https://developer.huawei.com/consumer/cn/
  12.           this.controller.loadUrl('https://developer.huawei.com/consumer/cn/');
  13.         } catch (error) {
  14.           let e: BusinessError = error as BusinessError;
  15.           console.error(`ErrorCode: ${e.code},  Message: ${e.message}`);
  16.         }
  17.       })
  18.       Web({
  19.         src: 'https://www.baidu.com/',
  20.         controller: this.controller
  21.       })
  22.     }
  23.     .height('100%')
  24.     .width('100%')
  25.   }
  26. }
复制代码
  留意
如果盼望看到结果,必要在真机大概模仿器上运行代码,Previewer暂不支持Web组件的预览结果。
  三、加载本地页面

   将本地页面文件放在应用的rawfile目录下,开发者可以在Web组件创建的时间指定默认加载的本地页面 ,而且加载完成后可通过调用loadUrl()接口变更当前Web组件的页面。

在下面的示例中展示加载本地页面文件的方法:

  示例代码
  1. import { webview } from '@kit.ArkWeb';
  2. import { BusinessError } from '@kit.BasicServicesKit';
  3. import { promptAction } from '@kit.ArkUI';
  4. // 使用 ArkWeb构建页面 https://developer.huawei.com/consumer/cn/training/course/slightMooc/C101717497640610394
  5. @Entry
  6. @Component
  7. struct WebComponent {
  8.   controller: webview.WebviewController = new webview.WebviewController()
  9.   //加载网络页面
  10.   // private url: string = 'https://www.baidu.com/'
  11.   //加载本地页面
  12.   private url: Resource = $rawfile("testH.html")
  13.   build() {
  14.     Column() {
  15.       Row() {
  16.         Button('loadUrl').onClick(() => {
  17.           try {
  18.             // 点击按钮时,通过loadUrl,跳转到https://developer.huawei.com/consumer/cn/
  19.             // this.controller.loadUrl('https://developer.huawei.com/consumer/cn/');
  20.             if (this.controller.accessForward()) {
  21.               console.log("执行了 forward")
  22.               this.controller.forward()
  23.             } else {
  24.               console.log("执行了 loadUrl")
  25.               this.controller.loadUrl($rawfile("testH2.html"));
  26.             }
  27.           } catch (error) {
  28.             let e: BusinessError = error as BusinessError;
  29.             console.error(`loadUrl ErrorCode: ${e.code},  Message: ${e.message}`);
  30.           }
  31.         }).margin({ right: 20 })
  32.         Button('返回').onClick(() => {
  33.           try {
  34.             if (this.controller.accessBackward()) {
  35.               this.controller.backward()
  36.             } else {
  37.               promptAction.showToast({ message: "已经是首页了" })
  38.             }
  39.           } catch (error) {
  40.             let e: BusinessError = error as BusinessError;
  41.             console.error(`返回 ErrorCode: ${e.code},  Message: ${e.message}`);
  42.           }
  43.         })
  44.       }.margin({ top: 20 })
  45.       Web({
  46.         src: this.url,
  47.         controller: this.controller
  48.       })
  49.     }
  50.     .height('100%')
  51.     .width('100%')
  52.   }
  53. }
复制代码
将资源文件放置在应用的resources/rawfile目录下。
   

  结果图
   

  四、加载HTML格式的文本数据

   Web组件可以通过loadData()接口实现加载HTML格式的文本数据。当开发者不必要加载整个页面,只必要体现一些页面片段时,可通过此功能来快速加载页面。

示例代码
  1. import { webview } from '@kit.ArkWeb';
  2. import { BusinessError } from '@kit.BasicServicesKit';
  3. import { promptAction } from '@kit.ArkUI';
  4. // 使用 ArkWeb构建页面 https://developer.huawei.com/consumer/cn/training/course/slightMooc/C101717497640610394
  5. @Entry
  6. @Component
  7. struct WebComponent {
  8.   controller: webview.WebviewController = new webview.WebviewController()
  9.   //加载网络页面
  10.   // private url: string = 'https://www.baidu.com/'
  11.   //加载本地页面
  12.   private url: Resource = $rawfile("testH.html")
  13.   build() {
  14.     Column() {
  15.       Row() {
  16.         Button('loadUrl').onClick(() => {
  17.           try {
  18.             if (this.controller.accessForward()) {
  19.               console.log("执行了 forward")
  20.               this.controller.forward()
  21.             } else {
  22.               console.log("执行了 loadUrl")
  23.               //加载网络页面
  24.               let tempUrl = "https://developer.huawei.com/consumer/cn/"
  25.               //加载本地页面
  26.               let tempUrlRes = $rawfile("testH2.html")
  27.               // this.controller.loadUrl(tempUrlRes);
  28.               // 点击按钮时,通过loadData,加载HTML格式的文本数据
  29.               this.controller.loadData(
  30.                 "<html><body bgcolor="white">Source:<pre>source</pre><p>加载HTML格式的文本数据</P></body></html>",
  31.                 "text/html",
  32.                 "UTF-8"
  33.               );
  34.             }
  35.           } catch (error) {
  36.             let e: BusinessError = error as BusinessError;
  37.             console.error(`loadUrl ErrorCode: ${e.code},  Message: ${e.message}`);
  38.           }
  39.         }).margin({ right: 20 })
  40.         Button('返回').onClick(() => {
  41.           try {
  42.             if (this.controller.accessBackward()) {
  43.               this.controller.backward()
  44.             } else {
  45.               promptAction.showToast({ message: "已经是首页了" })
  46.             }
  47.           } catch (error) {
  48.             let e: BusinessError = error as BusinessError;
  49.             console.error(`返回 ErrorCode: ${e.code},  Message: ${e.message}`);
  50.           }
  51.         })
  52.       }.margin({ top: 20 })
  53.       Web({
  54.         src: this.url,
  55.         controller: this.controller
  56.       })
  57.     }
  58.     .height('100%')
  59.     .width('100%')
  60.   }
  61. }
复制代码
结果图
   

  五、动态创建Web组件

   支持命令式创建Web组件,这种方式创建的组件不会立即挂载到组件树,即不会对用户呈现(组件状态为Hidden和InActive),开发者可以在后续使用中按需动态挂载。后台启动的Web实例不建议超过200个。
  1. import { createNWeb } from '../pages/web/CommonWeb'
  2. // 载体Ability
  3. // EntryAbility.ets
  4. import { createNWeb } from "../pages/common"
  5. onWindowStageCreate(windowStage: window.WindowStage): void {
  6.   windowStage.loadContent('pages/Index', (err, data) => {
  7.     // 创建Web动态组件(需传入UIContext),loadContent之后的任意时机均可创建
  8.     createNWeb("https://www.example.com", windowStage.getMainWindowSync().getUIContext());
  9.     if (err.code) {
  10.       return;
  11.     }
  12.   });
  13. }
复制代码
CommonWeb.ets代码
  1. import { webview } from '@kit.ArkWeb'
  2. import { NodeController, BuilderNode, Size, FrameNode, UIContext } from '@kit.ArkUI';
  3. /*
  4.   动态创建Web组件 https://developer.huawei.com/consumer/cn/training/course/slightMooc/C101717497640610394
  5. 支持命令式创建Web组件,这种方式创建的组件不会立即挂载到组件树,即不会对用户呈现(组件状态为Hidden和InActive),
  6. 开发者可以在后续使用中按需动态挂载。后台启动的Web实例不建议超过200个。
  7. */
  8. // @Builder中为动态组件的具体组件内容
  9. // Data为入参封装类
  10. class Data {
  11.   url: string = "https://developer.huawei.com/consumer/cn/";
  12.   controller: WebviewController = new webview.WebviewController();
  13. }
  14. @Builder
  15. function WebBuilder(data: Data) {
  16.   Column() {
  17.     Web({ src: data.url, controller: data.controller })
  18.       .width("100%")
  19.       .height("100%")
  20.   }
  21. }
  22. let wrap = wrapBuilder<Data[]>(WebBuilder);
  23. // 用于控制和反馈对应的NodeContainer上的节点的行为,需要与NodeContainer一起使用
  24. export class myNodeController extends NodeController {
  25.   private rootnode: BuilderNode<Data[]> | null = null;
  26.   // 必须要重写的方法,用于构建节点数、返回节点挂载在对应NodeContainer中
  27.   // 在对应NodeContainer创建的时候调用、或者通过rebuild方法调用刷新
  28.   makeNode(uiContext: UIContext): FrameNode | null {
  29.     console.log(" uicontext is undefined : " + (uiContext === undefined));
  30.     if (this.rootnode != null) {
  31.       // 返回FrameNode节点
  32.       return this.rootnode.getFrameNode();
  33.     }
  34.     // 返回null控制动态组件脱离绑定节点
  35.     return null;
  36.   }
  37.   // 当布局大小发生变化时进行回调
  38.   aboutToResize(size: Size) {
  39.     console.log("aboutToResize width : " + size.width + " height : " + size.height)
  40.   }
  41.   // 当controller对应的NodeContainer在Appear的时候进行回调
  42.   aboutToAppear() {
  43.     console.log("aboutToAppear")
  44.   }
  45.   // 当controller对应的NodeContainer在Disappear的时候进行回调
  46.   aboutToDisappear() {
  47.     console.log("aboutToDisappear")
  48.   }
  49.   // 此函数为自定义函数,可作为初始化函数使用
  50.   // 通过UIContext初始化BuilderNode,再通过BuilderNode中的build接口初始化@Builder中的内容
  51.   initWeb(url: string, uiContext: UIContext, control: WebviewController) {
  52.     if (this.rootnode != null) {
  53.       return;
  54.     }
  55.     // 创建节点,需要uiContext
  56.     this.rootnode = new BuilderNode(uiContext)
  57.     // 创建动态Web组件
  58.     this.rootnode.build(wrap, { url: url, controller: control })
  59.   }
  60. }
  61. // 创建Map保存所需要的NodeController
  62. let NodeMap: Map<string, myNodeController | undefined> = new Map();
  63. // 创建Map保存所需要的WebViewController
  64. let controllerMap: Map<string, WebviewController | undefined> = new Map();
  65. // 初始化需要UIContext 需在Ability获取
  66. export const createNWeb = (url: string, uiContext: UIContext) => {
  67.   // 创建NodeController
  68.   let baseNode = new myNodeController();
  69.   let controller = new webview.WebviewController();
  70.   // 初始化自定义Web组件
  71.   baseNode.initWeb(url, uiContext, controller);
  72.   controllerMap.set(url, controller)
  73.   NodeMap.set(url, baseNode);
  74. }
  75. // 自定义获取NodeController接口
  76. export const getNWeb = (url: string): myNodeController | undefined => {
  77.   return NodeMap.get(url);
  78. }
复制代码
WebIndex.ets代码
  1. // 使用NodeController的Page页
  2. // WebIndex.ets
  3. import { getNWeb } from "./CommonWeb"
  4. @Entry
  5. @Component
  6. struct WebIndex {
  7.   build() {
  8.     Row() {
  9.       Column() {
  10.         // NodeContainer用于与NodeController节点绑定,rebuild会触发makeNode
  11.         // Page页通过NodeContainer接口绑定NodeController,实现动态组件页面显示
  12.         NodeContainer(getNWeb("https://developer.huawei.com/consumer/cn/develop/"))
  13.           .height("90%")
  14.           .width("100%")
  15.       }
  16.       .width('100%')
  17.     }
  18.     .height('100%')
  19.   }
  20. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

tsx81429

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表