ArkWeb适配与开发

117 阅读3分钟
ArkWeb简介:

(1)概念介绍: Web组件用于在应用程序中显示Web页面内容,为开发者提供页面加载、页面交互、页面调试等能力。可以用于实现移动端的混合式开发(Hybrid App ):

  • 页面加载:Web组件提供了基础的前端页面加载的能力,包括加载网络页面、本地页面以及html格式文本数据。
  • 页面交互:Web组件提供丰富的页面交互的方式,包括:应用侧使用前端页面JavaScript等能力,设置前端页面深色模式,新窗口中加载页面,位置权限管理,Cookie管理。
  • 页面调试:Web组件支持使用Devtools工具调试前端页面

(2)ArkWebAPI参考

Web组件:提供具有网页显示能力的一种组件。

image.png

Webview:提供web控制能力的相关接口。

image.png

(3)Web组件的生命周期

image.png

Web页面加载与显示
  1. 加载网络页面
  • 开发者可以在Web组件创建时,指定默认加载的网络页面。在默认页面加载完成后,如果开发者需要变更此Web组件显示的网络页面,可以通过调用loadUrl()接口加载指定的网页。
@Entry @Component 
struct WebComponent { 
    webviewController: web_webview.WebviewController = new web_webview.WebviewController();
    build() { 
        Column() { 
            Button('loadUrl').onClick(() => { 
                try { // 点击按钮时,通过loadUrl,跳转到www.example1.com 
                    this.webviewController.loadUrl('www.example1.com'); 
                } catch (error) { ... } })
                // 组件创建时,加载www.example.com 
                Web({ src: 'www.example.com', controller: this.webviewController})
           } 
    } 
}
  1. 加载本地页面
  • 将本地页面文件放在应用的rawfile目录下,开发者可以在Web组件创建的时候指定默认加载的本地页面,并且加载完成后可通过调用loadUrl()接口变更当前Web组件的页面。
import web_webview from '@ohos.web.webview';
import business_error from '@ohos.base';
@Entry
@Component
struct WebComponent {
  webviewController: web_webview.WebviewController = new web_webview.WebviewController();
  build() {
    Column() {
      Button('loadUrl')
        .onClick(() => {
          try {
            // 点击按钮时,通过loadUrl,跳转到local1.html
            this.webviewController.loadUrl($rawfile("local1.html"));
          } catch (error) {
            ...
          }
        })
      // 组件创建时,通过$rawfile加载本地文件local.html
      Web({ src: $rawfile("local.html"), controller: this.webviewController })
    }
  }
}
  1. 加载HTML格式数据
@Entry
@Component
struct WebComponent {
  controller: web_webview.WebviewController = new web_webview.WebviewController();
  build() {
    Column() {
      Button('loadData')
        .onClick(() => {
          try {
            // 点击按钮时,通过loadData,加载HTML格式的文本数据
            this.controller.loadData(
              "<html><body bgcolor="white">Source:<pre>source</pre></body></html>",
              "text/html",
              "UTF-8"
            );
          } catch (error) {
           // …
          }
        })
      // 组件创建时,加载www.example.com
      Web({ src: 'www.example.com', controller: this.controller })
    }
  }
}
应用侧与前端页面交互
  1. 应用侧调用前端页面函数 应用侧可以通过runJavaScript()方法调用前端页面的JavaScript相关函数。

前端页面代码

<!-- index.html -->
<!DOCTYPE html>
<html>
<body>
<script>
function htmlTest() {
  console.info('JavaScript Hello World! ');
}
</script>
</body>
</html>

应用侧代码

import web_webview from '@ohos.web.webview';
@Entry
@Component
struct WebComponent {
  webviewController: web_webview.WebviewController
    = new web_webview.WebviewController();
  build() {
    Column() {
      Button('runJavaScript')
        .onClick(() => {
          this.webviewController.runJavaScript('htmlTest()');
        })
      Web({ src: $rawfile('index.html'), controller: this.webviewController})
    }
  }
}
  1. 前端页面调用应用侧函数
    使用Web组件将应用侧代码注册到前端页面中,注册完成之后,前端页面中使用注册的对象名称就可以调用应用侧的函数, 实现在前端页面中调用应用侧方法。

    注册应用侧代码有两种方式
  • 在Web组件初始化调用,使用javaScriptProxy()接口。

  • 在Web组件初始化完成后调用,使用registerJavaScriptProxy()接口。

    函数传参支持复杂类型

  • 应用侧和前端页面之间传递Array

  • 应用侧和前端页面之间传递不带Function的Dictionary

  • 应用侧调用前端页面的Callback

  • 应用侧调用前端页面Object里的Function

  • 前端页面调用应用侧Object里的Function

  • 支持Promise场景

    前端页面代码

<!-- index.html -->
  <!DOCTYPE html>
  <html>
  <body>
  <button type="button" onclick="callArkTS()">Click Me!</button>
  <p id="demo"></p>
  <script>
  function callArkTS() {
    let str = testObjName.test();
    document.getElementById("demo").innerHTML = str;
    console.info('ArkTS Hello World! :' + str);
  }
  </script>
  </body>
  </html>

应用侧代码:方法1 javaScriptProxy()

@Entry
@Component
struct WebComponent {
  webviewController: web_webview.WebviewController
    = new web_webview.WebviewController();
  // 声明需要注册的对象
  @State testObj: TestClass = new TestClass();
  build() {
    Column() {
      // web组件加载本地index.html页面
      Web({ src: $rawfile('index.html'), controller: this.webviewController})
        // 将对象注入到web端
        .javaScriptProxy({
          object: this.testObj,
          name: "testObjName",
          methodList: ["test"],
          controller: this.webviewController
        })
    }
  }
}

方法2 registerJavaScriptProxy()

import web_webview from '@ohos.web.webview';
class TestClass {
  constructor() {
  }
  test(): string {
    return 'ArkTS Hello World!';
  }
}
class TestClass {
  constructor() {
  }
  test(): string {
    return "ArkUI Web Component";
  }
  toString(): void {
    console.log('Web Component toString');
  }
}
@State testObj: testClass = new TestClass();
this.webviewController.refresh();
this.webviewController.registerJavaScriptProxy(this.testObj, "testObjName", ["test", "toString"]);
Web({ src: $rawfile('index.html'), controller: this.webviewController })

registerJavaScriptProxy函数传参支持以下复杂类型

  • 应用侧和前端页面之间传递Array
test(): Array{ 
    return [1, 2, 3, 4] 
}
  • 应用侧和前端页面之间传递不带Function的Dictionary
test(): student {
    let st: student = {name:"jeck", age:"12"} return st 
}
  • 应用侧调用前端页面的Callback
test(param: Function): void {
    param("call callback");
}
  • 应用侧调用前端页面Object里的Function
test(param: ESObject): void {
    param.hello("call obj func");
}
  • 前端页面调用应用侧Object里的Function
 test(): ESObject { 
     return this.ObjReturn
 } 
  • 支持Promise场景
test(): Promise {
    let p: Promise = new Promise(); return p;
}
自定义页面请求响应(响应拦截)

使用场景:Web组件支持在应用拦截到页面请求后自定义响应请求能力。开发者通过 onInterceptRequest() 接口来实现自 定义资源请求响应 。自定义请求能力可以用于开发者自定义Web页面响应、自定义文件资源响应等场景。

Web({ src: $rawfile('index.html'), controller: this.controller })
  .onInterceptRequest((event) => {
    if (event) {
      console.info('url:' + event.request.getRequestUrl());
      // 拦截页面请求
      if (event.request.getRequestUrl() !== 'https://www.example.com/test.html') {
        return null;
      }
    }
    // 构造响应数据
    this.responseResource.setResponseData(this.webData);
    this.responseResource.setResponseEncoding('utf-8');
    this.responseResource.setResponseMimeType('text/html');
    this.responseResource.setResponseCode(200);
    this.responseResource.setReasonMessage('OK');
    return this.responseResource;
  })