头图

【高心星出品】

Web组件的使用

ArkWeb(方舟Web)提供了Web组件,用于在应用程序中显示Web页面内容。常见使用场景包括:

  • 应用集成Web页面:应用可以在页面中使用Web组件,嵌入Web页面内容,以降低开发成本,提升开发、运营效率。
  • 浏览器网页浏览场景:浏览器类应用可以使用Web组件,打开三方网页,使用无痕模式浏览Web页面,设置广告拦截等。
  • 小程序:小程序类宿主应用可以使用Web组件,渲染小程序的页面。

加载网页资源

private webcontroller:WebviewController=new webview.WebviewController()//控制器
....
Web({src:'https://www.sohu.com/',controller:this.webcontroller})
  .margin(20)
名称类型必填说明
srcstring \Resource网页资源地址。如果访问本地资源文件,请使用$rawfile或者resource协议。如果加载应用包外沙箱路径的本地资源文件(文件支持html和txt类型),请使用file://沙箱文件路径。src不能通过状态变量(例如:@State)动态更改地址,如需更改,请通过loadUrl()重新加载。
controllerWebviewController9+控制器。从API Version 9开始,WebController不再维护,建议使用WebviewController替代。

这里的src可以提供网络地址,也可以提供项目中本地网页代码资源。

项目结构

在这里插入图片描述

项目代码
import { webview } from '@kit.ArkWeb';

@Entry
@Component
struct Index {
  @State message: string = 'Hello World';
  private webcontroller:WebviewController=new webview.WebviewController()
  build() {
    Column(){
      Button('重新加载')
        .onClick(()=>{
          //重新加载本地资源
         this.webcontroller.loadUrl($rawfile('test.html'))
        })
        //加载网络地址
      Web({src:'https://www.sohu.com/',controller:this.webcontroller})
        .margin(20)
    }
    .width('100%')
    .height('100%')
  }
}

在这里插入图片描述

Web组件的生命周期方法

Web组件提供了丰富的组件生命周期回调接口,通过这些回调接口,开发者可以感知Web组件的生命周期状态变化,进行相关的业务处理。

Web组件的状态主要包括:Controller绑定到Web组件、网页加载开始、网页加载进度、网页加载结束、页面即将可见等。

img

  • onControllerAttached事件:当Controller成功绑定到Web组件时触发该回调,且禁止在该事件回调前调用Web组件相关的接口,否则会抛出js-error异常。推荐在此事件中注入JS对象registerJavaScriptProxy、设置自定义用户代理setCustomUserAgent,可以在回调中使用loadUrl,getWebId等操作网页不相关的接口。但因该回调调用时网页还未加载,因此无法在回调中使用有关操作网页的接口,例如zoomIn、zoomOut等。
  • onLoadIntercept事件:当Web组件加载url之前触发该回调,用于判断是否阻止此次访问。默认允许加载。
  • onOverrideUrlLoading事件:当URL将要加载到当前Web中时,让宿主应用程序有机会获得控制权,回调函数返回true将导致当前Web中止加载URL,而返回false则会导致Web继续照常加载URL。onLoadIntercept接口和onOverrideUrlLoading接口行为不一致,触发时机也不同,所以在应用场景上存在一定区别。主要是在LoadUrl和iframe(HTML标签,表示HTML内联框架元素,用于将另一个页面嵌入到当前页面中)加载时,onLoadIntercept事件会正常回调到,但onOverrideUrlLoading事件在LoadUrl加载时不会触发,在iframe加载HTTP(s)协议或about:blank时也不会触发。详细介绍请见onLoadIntercept和onOverrideUrlLoading的说明。
  • onInterceptRequest事件:当Web组件加载url之前触发该回调,用于拦截url并返回响应数据。
  • onPageBegin事件:网页开始加载时触发该回调,且只在主frame(表示一个HTML元素,用于展示HTML页面的HTML元素)触发。如果是iframe或者frameset(用于包含frame的HTML标签)的内容加载时则不会触发此回调。多frame页面有可能同时开始加载,即使主frame已经加载结束,子frame也有可能才开始或者继续加载中。同一页面导航(片段、历史状态等)或者在提交前失败、被取消的导航等也不会触发该回调。
  • onProgressChange事件:告知开发者当前页面加载的进度。多frame页面或者子frame有可能还在继续加载而主frame可能已经加载结束,所以在onPageEnd事件后依然有可能收到该事件。
  • onPageEnd事件:网页加载完成时触发该回调,且只在主frame触发。多frame页面有可能同时开始加载,即使主frame已经加载结束,子frame也有可能才开始或者继续加载中。同一页面导航(片段、历史状态等)或者在提交前失败、被取消的导航等也不会触发该回调。推荐在此回调中执行JavaScript脚本loadUrl等。需要注意的是收到该回调并不能保证Web绘制的下一帧将反映此时DOM的状态。
  • onPageVisible事件:Web回调事件。渲染流程中当HTTP响应的主体开始加载,新页面即将可见时触发该回调。此时文档加载还处于早期,因此链接的资源比如在线CSS、在线图片等可能尚不可用。
  • onRenderExited事件:应用渲染进程异常退出时触发该回调,可以在此回调中进行系统资源的释放、数据的保存等操作。如果应用希望异常恢复,需要调用loadUrl接口重新加载页面。
  • onDisAppear事件:组件卸载消失时触发此回调。该事件为通用事件,指组件从组件树上卸载时触发的事件。
项目结构

在这里插入图片描述

import { webview } from '@kit.ArkWeb';
import { buffer } from '@kit.ArkTS';

@Entry
@Component
struct Index {
  @State message: string = 'Hello World';
  private webcontroller: WebviewController = new webview.WebviewController()

  build() {
    Column() {
      Button('重新加载')
        .onClick(() => {
          this.webcontroller.loadUrl($rawfile('test.html'))
        })
      Web({ src: 'https://www.sohu.com/', controller: this.webcontroller })
        .onControllerAttached(() => {
          //此时controller可以使用,一番设置或者注入js对象
          console.log('gxxt ', 'controller绑定web的时候调用')
        })
        .onLoadIntercept((event) => {
          // 获取请求地址  请求方法
          console.log('gxxt ', '即将加载俩  url= ' + event.data.getRequestUrl())
          // 返回true则拦截此次请求,false表示不拦截
          return false
        })
        .onInterceptRequest((event) => {
          console.log('gxxt 根据url 即将发起请求: ' + event.request.getRequestUrl())
          // 如果请求地址有https
          if (event.request.getRequestUrl().indexOf('https') >= 0) {
            //自己定义一个响应
            let webreqres = new WebResourceResponse()
            webreqres.setResponseEncoding('UTF-8')
            webreqres.setResponseMimeType('text/html')
            webreqres.setResponseCode(200)
            webreqres.setResponseData(this.getrawstr())
            return webreqres
          }
          // 否则 继续返回
          return null
        })
        .onPageBegin((event) => {
          //页面开始加载的时候调用
          console.log('gxxt  页面开始加载:' + event.url)
        })
        .onProgressChange((event) => {
          console.log('gxxt 加载进度: ' + event.newProgress)
        })
        .onPageEnd((event) => {
          console.log('gxxt 页面加载完毕: ' + event.url)
        })
        .margin(20)
    }
    .width('100%')
    .height('100%')
  }

  getrawstr() {
      //读取网页内容转换成字符串
    let buffer1 = getContext(this).resourceManager.getRawFileContentSync('intercept.html').buffer
    return buffer.from(buffer1).toString()
  }
}

在这里插入图片描述

网页导航

在前端页面点击网页中的链接时,Web组件默认会自动打开并加载目标网址。当前端页面替换为新的加载链接时,会自动记录已经访问的网页地址。可以通过forward()和backward()接口向前/向后浏览上一个/下一个历史记录。

例如点击后退键的时候,我们不再推出应用而是回到上一页,如果没有上一页再退出应用。

在这里插入图片描述

import { webview } from '@kit.ArkWeb';
import { buffer } from '@kit.ArkTS';

@Entry
@Component
struct Index {
  @State message: string = 'Hello World';
  private webcontroller: WebviewController = new webview.WebviewController()

  build() {
    Column() {
      Button('重新加载')
        .onClick(() => {
          this.webcontroller.loadUrl($rawfile('test.html'))
        })
      Web({ src: 'https://www.sohu.com/', controller: this.webcontroller })
        .margin(20)
    }
    .width('100%')
    .height('100%')
  }

  // getrawstr() {
  //   let buffer1 = getContext(this).resourceManager.getRawFileContentSync('intercept.html').buffer
  //   return buffer.from(buffer1).toString()
  // }
  onBackPress(): boolean | void {
  //   如果能后退就退到上一页
  if(this.webcontroller.accessBackward())
  {
    this.webcontroller.backward()
    // 拦截默认的back键操作
    return true

  }else{
    // 否则不拦截
    return false
  }
  }
}

高心星
1 声望1 粉丝

华为开发者专家(HDE)。 10年教学经验,兼任多家科技公司技术顾问。先后从事JavaEE项目开发、Python爬虫、HarmonyOS移动应用开发等课程的教学工作。参与开发《鸿蒙应用开发基础》和《鸿蒙项目实战》等课程。