鸿蒙开发-ArkWeb

显示网页内容,提供加载、交互、调试等能力,实现移动端H5混合开发

  • 加载:网页、离线页、html文本
  • 交互:设置页面深色模式,新窗口中打开,位置权限管理,Cookie管理,使用JS脚本
  • 调试:使用Devtools工具调试网页

在这里插入图片描述
在这里插入图片描述

网页加载:loadUrl

webviewController = new webview.WebviewController()
Button().onClick(() => {
this.webviewController.loadUrl('www.bing.com’)
})
Web({ src: 'www.example.com', controller: this.webviewController})

本地页面

在这里插入图片描述

this.webviewController.loadUrl($rawfile("local1.html"))

// 通过$rawfile加载本地文件
Web({ src: $rawfile("local.html"), controller: this.webviewController })

加载HTML片段:loadData

this.controller.loadData(
  "<html><body bgcolor=\"white\">Source:<pre>source</pre></body></html>",
  "text/html",
   "UTF-8")

forward()、backward() 前进/后退

if (this.webviewController.accessBackward()) {
    this.webviewController.backward()
}

当点击网页链接需要跳转到应用内其他页面时,可用onLoadIntercept()

route.html

<!-- route.html -->
<!DOCTYPE html>
<html>
<body>
  <div>
      <a href=“native://pages/Profile”>我的</a>
   </div>
</body>
</html>

首页Index.ets

struct WebComponent {
  webviewController = new webview.WebviewController();

  build() {
    Column() {
      Web({ src: $rawfile('route.html'), controller: this.webviewController })
        .onLoadIntercept((event) => {
          if (event) {
            let url: string = event.data.toString();
            if (url.indexOf('native://') === 0) {

	   router.pushUrl({ url:url.substring(9) })
              return true;
            }
          }
          return false;
        })
    }
  }
}

Profile.ets

@Entry
@Component
struct Profile {}

可实现跳转到其他应用

@Entry
@Component
struct WebComponent {
  webviewController = new webview.WebviewController();

  build() {
    Column() {
      Web({ src: $rawfile('call.html'), controller: this.webviewController})
        .onLoadIntercept((event) => {
          if (event) {
            let url: string = event.data.toString();
            // 判断链接是否为拨号链接
            if (url.indexOf('tel://') === 0) {
              // 跳转拨号界面
              call.makeCall(url.substring(6), (err) => {
                ...
              });
              return true;
            }
          }
          return false;
        })
    }
  }
}

页面call.html

<!-- call.html -->
<!DOCTYPE html>
<html>
<body>
  <div>
    <a href="tel://13912345678">拨打电话</a>
  </div>
</body>
</html>

可通过runJavaScript()方法调用网页中的JavaScript相关函数。

将ArkTS代码注册到网页中,使用javaScriptProxy() 或 registerJavaScriptProxy() 在网页中调用。

在这里插入图片描述

通过runJavaScript()方法调用

<!-- index.html -->
<!DOCTYPE html>
<html>
<body>
<script>
    function htmlTest() {
        console.info('JavaScript Hello World! ');
    }
</script>
</body>
</html>
@Entry
@Component
struct WebComponent {
  webviewController = new webview.WebviewController();

  build() {
    Column() {
      Button('runJavaScript')
        .onClick(() => {
           this.webviewController.runJavaScript('htmlTest()');
        })
      Web({ src: $rawfile('index.html'), controller: this.webviewController})
    }
  }
}

将ArkTS代码注册到网页后,使用注册对象名就可以调用ArkTS函数

两种方式:

  • 在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、网页使用注册对象名,调用应用的函数。
2、在Web组件初始化使用javaScriptProxy()接口。
3、该方法在Web API中。

class TestClass {
  constructor() {
  }

  test(): string {
    return 'ArkTS Hello World!';
  }
}

@Entry
@Component
struct WebComponent {
  webviewController = new 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
        })
    }
  }
}

1、在Web组件初始化完成后,使用registerJavaScriptProxy()接口。
2、使用registerJavaScriptProxy()接口注册方法时,注册后需调用refresh()接口生效。

<!-- 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>
class TestClass {
  constructor() {
  }

  test(): string {
    return "ArkUI Web Component";
  }

  toString(): void {
    console.log('Web Component toString');
  }
}

webviewController = new webview.WebviewController();
@State testObj: testClass = new TestClass();

this.webviewController.refresh();
this.webviewController.registerJavaScriptProxy(this.testObj, "testObjName", ["test", "toString"]);

Web({ src: $rawfile('index.html'), controller: this.webviewController })

函数传参支持一些复杂类型

Array

test(): Array<Number>{
  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");
}

调用ArkTS的Object里的Function

test(): ESObject {
  return this.ObjReturn
}

支持Promise

test(): Promise<string> {
  let p: Promise<string> = new Promise();
  return p;
}

在这里插入图片描述
建立数据通道
可以用createWebMessagePorts()创建消息端口来实现两端通信

在这里插入图片描述

  • JSBridge
    • 函数的相互调用,不需要一直保持通道。
  • WebMessagePorts
    • 建立通道,实时监听,持续消耗资源。
    • 对于有双向通信需求的场景,数据实时更新,聊天应用,大文件等更稳定。

自定义请求响应(拦截)

      Web({ src: $rawfile('index.html'), controller: this.controller })
        .onInterceptRequest((event) => {
          if (event) {
	 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
        })
@State webData: string = '<!DOCTYPE html>\n' +
  '<html>\n'+
  '<head>\n'+
  '<title>intercept test</title>\n'+
  '</head>\n'+
  '<body>\n'+
  '<h1>intercept ok</h1>\n'+
  '</body>\n'+
  '</html>'

缓存管理在移动应用中起着重要的作用。

  • 提升性能:将已访问过的页面、资源等保存在本地,下次加载同样内容直接从本地缓存获取。

  • 离线访问:无网也可访问之前看过的页面或资源。

  • 节省流量:减少联网依赖,对于网络条件差或流量限制下很重要。

cacheMode()配置缓存:

  • Default : 优先使用未过期的缓存,否则从网络获取
  • None : 加载资源使用cache,如果缓存中无该资源则从网络中获取
  • Online : 在线模式
  • Only :离线模式
struct WebComponent {
  @State mode: CacheMode = CacheMode.None;
  controller = new webview.WebviewController
  build() {
    Column() {
      Button('removeCache')
        .onClick(() => {
          try {
            // 设置为true同时清除内存和文件缓存,false只清除内存缓存
            this.controller.removeCache(true);
          } catch (error) {}
        })
      Web({ src: 'www.example.com', controller: this.controller })
        .cacheMode(this.mode)
    }
  }
}

DOM Storage(页面级存储)

  • Session Storage:Session Storage是一种临时的存储机制,存储的数据与会话(session)的生命周期相关联。它只在当前会话期间有效,当会话结束(浏览器关闭)时,Session Storage中的数据会被自动释放。这意味着在同一个会话期间,数据可以在不同的页面间进行共享和传递。

  • Local Storage:Local Storage是一种持久化的存储机制,它允许将数据存储在浏览器的文件系统中的应用目录下,数据不会因会话结束而消失。Local Storage中的数据可以长期保存,甚至在用户关闭浏览器后再次打开时仍然可用。

无痕浏览。此模式下cookies、 缓存等不会保存在本地。

@Entry
@Component
struct WebComponent {
 controller = new web_webview.WebviewController()
 build() {
   Column() {
     Web({ src: 'www.example.com', controller: this.controller, incognitoMode: true })


      Button('isIncognitoMode')
        .onClick(() => {
            ...
            let result = this.controller.isIncognitoMode();
            ...
        })
   }
 }
}

在这里插入图片描述
预解析和预连接
1)可通过prepareForPageLoad()来预解析或者预连接将要加载的页面。
在Web组件的onAppear中对要加载的页面进行预连接。

      Web({ src: 'https://111.com/', controller: this.webviewController})
        .onAppear(() => {
            // 第二个参数为true代表要进行预连接,如果为false该接口只会对网址进行dns预解析
            // 第三个参数为要预连接socket的个数。最多允许6个。
	    webview.WebviewController.prepareForPageLoad('https://111.com/', true, 2);
        })

2)也可通过initializeBrowserEngine()提前初始化内核。这种方式适合提前对首页进行预解析、预连接。

webview.WebviewController.initializeWebEngine();
webview.WebviewController.prepareForPageLoad("https://111.com/", true, 2);

如果未来要访问的页面可预见,不妨使用prefetchPage()预加载

  • 只预先下载页面资源,不执行JavaScript代码
struct WebComponent {
  webviewController = new webview.WebviewController()
  build() {
    Column() {
      Web({ src: 'https://111.com', controller: this.webviewController})
        .onPageEnd(() => {
            // 上一个页面加载完成后,预加载下一个
            this.webviewController.prefetchPage('https://222.com');
        })
    }
  }
}

1、文件上传
可以使用onShowFileSelector()接口来处理前端页面文件上传的请求

2、下载
通过WebDownloadDelegate来监听页面触发的下载任务,将下载的进度通知给应用,包括下载进度、下载速度、下载错误码等。

3、设置深色模式
darkMode()可以配置不同的深色模式:
WebDarkMode.Off 关闭
WebDarkMode.On 开启并跟随网页
WebDarkMode.Auto 开启并跟随系统
4、管理位置权限
可以通过onGeolocationShow()对某个网站进行位置权限管理。Web组件根据接口响应结果,决定是否赋予前端页面权限。

5、UserAgent字段设置
告诉服务器请求的来源和客户端的基本特性,以便提供适配的内容或服务
setCustomUserAgent:自定义
getUserAgent:获取当前默认
getCustomUserAgent:获取自定义

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值