【鸿蒙开发】第十八章 Web组件(二)

接上一章节 【鸿蒙开发】第十七章 Web组件(一)

4 H5与端侧交互

4.1 应用侧调用前端页面函数

应用侧可以通过runJavaScript()方法调用前端页面的JavaScript相关函数。
在下面的示例中,点击应用侧的“runJavaScript”按钮时,来触发前端页面的htmlTest()方法。

  1. 前端页面代码。
<!-- index.html -->
<!DOCTYPE html>
<html>
<body>
<script>function htmlTest() {console.info('JavaScript Hello World! ');}
</script>
</body>
</html>
  1. 应用侧代码。
// xxx.ets
import web_webview from '@ohos.web.webview';@Entry
@Component
struct WebComponent {webviewController: web_webview.WebviewController = new web_webview.WebviewController();build() {Column() {Web({ src: $rawfile('index.html'), controller: this.webviewController})Button('runJavaScript').onClick(() => {this.webviewController.runJavaScript('htmlTest()');})Web({ src: $rawfile('index.html'), controller: this.webviewController})}}
}

4.2 前端页面调用应用侧函数

开发者使用Web组件将应用侧代码注册到前端页面中,注册完成之后,前端页面中使用注册的对象名称就可以调用应用侧的函数,实现在前端页面中调用应用侧方法。

注册应用侧代码有两种方式,一种在Web组件初始化调用,使用javaScriptProxy()接口。另外一种在Web组件初始化完成后调用,使用registerJavaScriptProxy()接口。

在下面的示例中,将test()方法注册在前端页面中, 该函数可以在前端页面触发运行。

  1. javaScriptProxy()接口使用示例如下。
// xxx.ets
import web_webview from '@ohos.web.webview';class testClass {constructor() {}test(): string {return 'ArkTS Hello World!';}
}@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})}}
}
  1. 应用侧使用registerJavaScriptProxy()接口注册。
// xxx.ets
import web_webview from '@ohos.web.webview';
import business_error from '@ohos.base';class testClass {constructor() {}test(): string {return "ArkUI Web Component";}toString(): void {console.log('Web Component toString');}
}@Entry
@Component
struct Index {webviewController: web_webview.WebviewController = new web_webview.WebviewController();@State testObj: testClass = new testClass();build() {Column() {Button('refresh').onClick(() => {try {this.webviewController.refresh();} catch (error) {let e: business_error.BusinessError = error as business_error.BusinessError;console.error(`ErrorCode: ${e.code},  Message: ${e.message}`);}})Button('Register JavaScript To Window').onClick(() => {try {this.webviewController.registerJavaScriptProxy(this.testObj, "testObjName", ["test", "toString"]);} catch (error) {let e: business_error.BusinessError = error as business_error.BusinessError;console.error(`ErrorCode: ${e.code},  Message: ${e.message}`);}})Web({ src: $rawfile('index.html'), controller: this.webviewController })}}
}
  • 说明:
    使用registerJavaScriptProxy()接口注册方法时,注册后需调用refresh()接口生效。
  1. index.html前端页面触发应用侧代码。
<!-- 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>

4.2.1 复杂类型使用方法

  • 应用侧和前端页面之间传递Array。
import web_webview from '@ohos.web.webview';
import business_error from '@ohos.base';class testClass {constructor() {}test(): Array<Number>{return [1, 2, 3, 4]}toString(param:String): void {console.log('Web Component toString' + param);}
}@Entry
@Component
struct Index {webviewController: web_webview.WebviewController = new web_webview.WebviewController();@State testObj: testClass = new testClass();build() {Column() {Button('refresh').onClick(() => {try {this.webviewController.refresh();} catch (error) {let e: business_error.BusinessError = error as business_error.BusinessError;console.error(`ErrorCode: ${e.code},  Message: ${e.message}`);}})Button('Register JavaScript To Window').onClick(() => {try {this.webviewController.registerJavaScriptProxy(this.testObj, "testObjName", ["test", "toString"]);} catch (error) {let e: business_error.BusinessError = error as business_error.BusinessError;console.error(`ErrorCode: ${e.code},  Message: ${e.message}`);}})Web({ src: $rawfile('index.html'), controller: this.webviewController })}}
}
<!-- index.html -->
<!DOCTYPE html>
<html>
<body>
<button type="button" onclick="callArkTS()">Click Me!</button>
<p id="demo"></p>
<script>function callArkTS() {testObjName.test().then((param)=>{testObjName.toString(param)}).catch((param)=>{testObjName.toString(param)})}
</script>
</body>
</html>
  • 应用侧和前端页面之间传递不带Function的Dictionary。
// xxx.ets
import web_webview from '@ohos.web.webview';
import business_error from '@ohos.base';class student {name: string = ''age: string = ''
}class testClass {constructor() {}test(): student {let st: student = {name:"jeck", age:"12"}return st}toString(param: ESObject): void {console.log('Web Component toString' + param["name"]);}
}@Entry
@Component
struct Index {webviewController: web_webview.WebviewController = new web_webview.WebviewController();@State testObj: testClass = new testClass();build() {Column() {Button('refresh').onClick(() => {try {this.webviewController.refresh();} catch (error) {let e: business_error.BusinessError = error as business_error.BusinessError;console.error(`ErrorCode: ${e.code},  Message: ${e.message}`);}})Button('Register JavaScript To Window').onClick(() => {try {this.webviewController.registerJavaScriptProxy(this.testObj, "testObjName", ["test", "toString"]);} catch (error) {let e: business_error.BusinessError = error as business_error.BusinessError;console.error(`ErrorCode: ${e.code},  Message: ${e.message}`);}})Web({ src: $rawfile('index.html'), controller: this.webviewController })}}
}
<!-- index.html -->
<!DOCTYPE html>
<html>
<body>
<button type="button" onclick="callArkTS()">Click Me!</button>
<p id="demo"></p>
<script>function callArkTS() {testObjName.toString(testObjName.test());}
</script>
</body>
</html>
  • 应用侧调用前端页面的Callback。
// xxx.ets
import web_webview from '@ohos.web.webview';
import business_error from '@ohos.base';class testClass {constructor() {}test(param: Function): void {param("call callback");}toString(param:String): void {console.log('Web Component toString' + param);}
}@Entry
@Component
struct Index {webviewController: web_webview.WebviewController = new web_webview.WebviewController();@State testObj: testClass = new testClass();build() {Column() {Button('refresh').onClick(() => {try {this.webviewController.refresh();} catch (error) {let e: business_error.BusinessError = error as business_error.BusinessError;console.error(`ErrorCode: ${e.code},  Message: ${e.message}`);}})Button('Register JavaScript To Window').onClick(() => {try {this.webviewController.registerJavaScriptProxy(this.testObj, "testObjName", ["test", "toString"]);} catch (error) {let e: business_error.BusinessError = error as business_error.BusinessError;console.error(`ErrorCode: ${e.code},  Message: ${e.message}`);}})Web({ src: $rawfile('index.html'), controller: this.webviewController })}}
}
<!-- index.html -->
<!DOCTYPE html>
<html>
<body>
<button type="button" onclick="callArkTS()">Click Me!</button>
<p id="demo"></p>
<script>function callArkTS() {testObjName.test(function(param){testObjName.toString(param)});}
</script>
</body>
</html>
  • 应用侧调用前端页面Object里的Function。
// xxx.ets
import web_webview from '@ohos.web.webview';
import business_error from '@ohos.base';class testClass {constructor() {}test(param: ESObject): void {param.hello("call obj func");}toString(param:String): void {console.log('Web Component toString' + param);}
}@Entry
@Component
struct Index {webviewController: web_webview.WebviewController = new web_webview.WebviewController();@State testObj: testClass = new testClass();build() {Column() {Button('refresh').onClick(() => {try {this.webviewController.refresh();} catch (error) {let e: business_error.BusinessError = error as business_error.BusinessError;console.error(`ErrorCode: ${e.code},  Message: ${e.message}`);}})Button('Register JavaScript To Window').onClick(() => {try {this.webviewController.registerJavaScriptProxy(this.testObj, "testObjName", ["test", "toString"]);} catch (error) {let e: business_error.BusinessError = error as business_error.BusinessError;console.error(`ErrorCode: ${e.code},  Message: ${e.message}`);}})Web({ src: $rawfile('index.html'), controller: this.webviewController })}}
}
<!-- index.html -->
<!DOCTYPE html>
<html>
<body>
<button type="button" onclick="callArkTS()">Click Me!</button>
<p id="demo"></p>
<script>// 写法1class Student {constructor(nameList) {this.methodNameListForJsProxy = nameList;}hello(param) {testObjName.toString(param)}}var st = new Student(["hello"])// 写法2//创建一个构造器,构造函数首字母大写function Obj1(){this.methodNameListForJsProxy=["hello"];this.hello=function(param){testObjName.toString(param)};}//利用构造器,通过new关键字生成对象var st1 = new Obj1();function callArkTS() {testObjName.test(st);testObjName.test(st1);}
</script>
</body>
</html>
  • 前端页面调用应用侧Object里的Function。
// xxx.ets
import web_webview from '@ohos.web.webview';
import business_error from '@ohos.base';class ObjOther {methodNameListForJsProxy: string[]constructor(list: string[]) {this.methodNameListForJsProxy = list}testOther(json:string): void {console.info(json)}
}class testClass {ObjReturn:ObjOtherconstructor() {this.ObjReturn =  new ObjOther(["testOther"]);}test(): ESObject {return this.ObjReturn}toString(param: string): void {console.log('Web Component toString' + param);}
}@Entry
@Component
struct Index {webviewController: web_webview.WebviewController = new web_webview.WebviewController();@State testObj: testClass = new testClass();build() {Column() {Button('refresh').onClick(() => {try {this.webviewController.refresh();} catch (error) {let e: business_error.BusinessError = error as business_error.BusinessError;console.error(`ErrorCode: ${e.code},  Message: ${e.message}`);}})Button('Register JavaScript To Window').onClick(() => {try {this.webviewController.registerJavaScriptProxy(this.testObj, "testObjName", ["test", "toString"]);} catch (error) {let e: business_error.BusinessError = error as business_error.BusinessError;console.error(`ErrorCode: ${e.code},  Message: ${e.message}`);}})Web({ src: $rawfile('index.html'), controller: this.webviewController })}}
}
<!-- index.html -->
<!DOCTYPE html>
<html>
<body>
<button type="button" onclick="callArkTS()">Click Me!</button>
<p id="demo"></p>
<script>function callArkTS() {testObjName.test().testOther("call other object func");}
</script>
</body>
</html>
  • Promise场景。
    第一种使用方法,在应用侧new Promise。
// xxx.ets
import web_webview from '@ohos.web.webview';
import business_error from '@ohos.base';class testClass {constructor() {}test(): Promise<string> {let p: Promise<string> = new Promise((resolve, reject) => {  setTimeout(() => {console.log('执行完成'); reject('fail');}, 10000);});return p;}toString(param:String): void {console.log(" " + param)}
}@Entry
@Component
struct Index {webviewController: web_webview.WebviewController = new web_webview.WebviewController();@State testObj: testClass = new testClass();build() {Column() {Button('refresh').onClick(() => {try {this.webviewController.refresh();} catch (error) {let e: business_error.BusinessError = error as business_error.BusinessError;console.error(`ErrorCode: ${e.code},  Message: ${e.message}`);}})Button('Register JavaScript To Window').onClick(() => {try {this.webviewController.registerJavaScriptProxy(this.testObj, "testObjName", ["test", "toString"]);} catch (error) {let e: business_error.BusinessError = error as business_error.BusinessError;console.error(`ErrorCode: ${e.code},  Message: ${e.message}`);}})Web({ src: $rawfile('index.html'), controller: this.webviewController })}}
}
<!-- index.html -->
<!DOCTYPE html>
<html>
<body>
<button type="button" onclick="callArkTS()">Click Me!</button>
<p id="demo"></p>
<script>function callArkTS() {testObjName.test().then((param)=>{testObjName.toString(param)}).catch((param)=>{testObjName.toString(param)})}
</script>
</body>
</html>

第二种使用方法,在前端页面new Promise。

// xxx.ets
import web_webview from '@ohos.web.webview';
import business_error from '@ohos.base';class testClass {constructor() {}test(param:Function): void {setTimeout( () => { param("suc") }, 10000)}toString(param:String): void {console.log(" " + param)}
}@Entry
@Component
struct Index {webviewController: web_webview.WebviewController = new web_webview.WebviewController();@State testObj: testClass = new testClass();build() {Column() {Button('refresh').onClick(() => {try {this.webviewController.refresh();} catch (error) {let e: business_error.BusinessError = error as business_error.BusinessError;console.error(`ErrorCode: ${e.code},  Message: ${e.message}`);}})Button('Register JavaScript To Window').onClick(() => {try {this.webviewController.registerJavaScriptProxy(this.testObj, "testObjName", ["test", "toString"]);} catch (error) {let e: business_error.BusinessError = error as business_error.BusinessError;console.error(`ErrorCode: ${e.code},  Message: ${e.message}`);}})Web({ src: $rawfile('index.html'), controller: this.webviewController })}}
}
<!-- index.html -->
<!DOCTYPE html>
<html>
<body>
<button type="button" onclick="callArkTS()">Click Me!</button>
<p id="demo"></p>
<script>function callArkTS() {let funpromisevar p = new Promise(function(resolve, reject){funpromise=(param)=>{resolve(param)}})testObjName.test(funpromise)p.then((param)=>{testObjName.toString(param)})}
</script>
</body>
</html>

4.3 建立应用侧与前端页面数据通道

前端页面和应用侧之间可以用createWebMessagePorts()接口创建消息端口来实现两端的通信

在下面的示例中,应用侧页面中通过createWebMessagePorts方法创建消息端口,再把其中一个端口通过postMessage()接口发送到前端页面,便可以在前端页面和应用侧之间互相发送消息。

  1. 应用侧代码。
// xxx.ets
import web_webview from '@ohos.web.webview';
import business_error from '@ohos.base';@Entry
@Component
struct WebComponent {controller: web_webview.WebviewController = new web_webview.WebviewController();ports: web_webview.WebMessagePort[] = [];@State sendFromEts: string = 'Send this message from ets to HTML';@State receivedFromHtml: string = 'Display received message send from HTML';build() {Column() {// 展示接收到的来自HTML的内容Text(this.receivedFromHtml)// 输入框的内容发送到HTMLTextInput({placeholder: 'Send this message from ets to HTML'}).onChange((value: string) => {this.sendFromEts = value;})Button('postMessage').onClick(() => {try {// 1、创建两个消息端口。this.ports = this.controller.createWebMessagePorts();// 2、在应用侧的消息端口(如端口1)上注册回调事件。this.ports[1].onMessageEvent((result: web_webview.WebMessage) => {let msg = 'Got msg from HTML:';if (typeof(result) === 'string') {console.info(`received string message from html5, string is: ${result}`);msg = msg + result;} else if (typeof(result) === 'object') {if (result instanceof ArrayBuffer) {console.info(`received arraybuffer from html5, length is: ${result.byteLength}`);msg = msg + 'lenght is ' + result.byteLength;} else {console.info('not support');}} else {console.info('not support');}this.receivedFromHtml = msg;})// 3、将另一个消息端口(如端口0)发送到HTML侧,由HTML侧保存并使用。this.controller.postMessage('__init_port__', [this.ports[0]], '*');} catch (error) {let e: business_error.BusinessError = error as business_error.BusinessError;console.error(`ErrorCode: ${e.code},  Message: ${e.message}`);}})// 4、使用应用侧的端口给另一个已经发送到html的端口发送消息。Button('SendDataToHTML').onClick(() => {try {if (this.ports && this.ports[1]) {this.ports[1].postMessageEvent(this.sendFromEts);} else {console.error(`ports is null, Please initialize first`);}} catch (error) {let e: business_error.BusinessError = error as business_error.BusinessError;console.error(`ErrorCode: ${e.code},  Message: ${e.message}`);}})Web({ src: $rawfile('xxx.html'), controller: this.controller })}}
}
  1. 前端页面代码。
<!--xxx.html-->
<!DOCTYPE html>
<html>
<head><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>WebView Message Port Demo</title>
</head>
<body><h1>WebView Message Port Demo</h1><div><input type="button" value="SendToEts" onclick="PostMsgToEts(msgFromJS.value);"/><br/><input id="msgFromJS" type="text" value="send this message from HTML to ets"/><br/></div><p class="output">display received message send from ets</p>
</body>
<script>
var h5Port;
var output = document.querySelector('.output');
window.addEventListener('message', function (event) {if (event.data === '__init_port__') {if (event.ports[0] !== null) {h5Port = event.ports[0]; // 1. 保存从应用侧发送过来的端口。h5Port.onmessage = function (event) {// 2. 接收ets侧发送过来的消息。var msg = 'Got message from ets:';var result = event.data;if (typeof(result) === 'string') {console.info(`received string message from html5, string is: ${result}`);msg = msg + result;} else if (typeof(result) === 'object') {if (result instanceof ArrayBuffer) {console.info(`received arraybuffer from html5, length is: ${result.byteLength}`);msg = msg + 'lenght is ' + result.byteLength;} else {console.info('not support');}} else {console.info('not support');}output.innerHTML = msg;}}}
})// 3. 使用h5Port向应用侧发送消息。
function PostMsgToEts(data) {if (h5Port) {h5Port.postMessage(data);} else {console.error('h5Port is null, Please initialize first');}
}
</script>
</html>

5 管理页面跳转及浏览记录导航

5.1 历史记录导航

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

在下面的示例中,点击应用的按钮来触发前端页面的后退操作。

// xxx.ets
import web_webview from '@ohos.web.webview';@Entry
@Component
struct WebComponent {webviewController: web_webview.WebviewController = new web_webview.WebviewController();build() {Column() {Button('loadData').onClick(() => {if (this.webviewController.accessBackward()) {this.webviewController.backward();}})Web({ src: 'https://www.example.com/cn/', controller: this.webviewController})}}
}

如果存在历史记录,accessBackward()接口会返回true。同样,您可以使用accessForward()接口检查是否存在前进的历史记录。如果您不执行检查,那么当用户浏览到历史记录的末尾时,调用forward()backward()接口时将不执行任何操作。

5.2 页面跳转

当点击网页中的链接需要跳转到应用内其他页面时,可以通过使用Web组件的onUrlLoadIntercept()接口来实现。

在下面的示例中,应用首页Index.ets加载前端页面route.html,在前端route.html页面点击超链接,可跳转到应用的ProfilePage.ets页面。

  1. 应用首页Index.ets页面代码。
// index.ets
import web_webview from '@ohos.web.webview';
import router from '@ohos.router';
@Entry
@Component
struct WebComponent {webviewController: web_webview.WebviewController = new web_webview.WebviewController();build() {Column() {Web({ src: $rawfile('route.html'), controller: this.webviewController }).onUrlLoadIntercept((event) => {if (event) {let url: string = event.data.getRequestUrl();if (url.indexOf('native://') === 0) {// 跳转其他界面router.pushUrl({ url:url.substring(9) })return true;}}return false;})}}
}
  1. route.html前端页面代码。
<!-- route.html -->
<!DOCTYPE html>
<html>
<body><div><a href="native://pages/ProfilePage">个人中心</a></div>
</body>
</html>
  1. 跳转页面ProfilePage.ets代码。
@Entry
@Component
struct ProfilePage {@State message: string = 'Hello World';build() {Column() {Text(this.message).fontSize(20)}}
}

5.3 跨应用跳转

Web组件可以实现点击前端页面超链接跳转到其他应用
在下面的示例中,点击call.html前端页面中的超链接,跳转到电话应用的拨号界面。

  1. 应用侧代码。
// xxx.ets
import web_webview from '@ohos.web.webview';
import call from '@ohos.telephony.call';@Entry
@Component
struct WebComponent {webviewController: web_webview.WebviewController = new web_webview.WebviewController();build() {Column() {Web({ src: $rawfile('call.html'), controller: this.webviewController}).onUrlLoadIntercept((event) => {if (event) {let url: string = event.data as string;// 判断链接是否为拨号链接if (url.indexOf('tel://') === 0) {// 跳转拨号界面call.makeCall(url.substring(6), (err) => {if (!err) {console.info('make call succeeded.');} else {console.info('make call fail, err is:' + JSON.stringify(err));}});return true;}}return false;})}}
}
  1. 前端页面call.html代码。
<!-- call.html -->
<!DOCTYPE html>
<html>
<body><div><a href="tel://xxx xxxx xxx">拨打电话</a></div>
</body>
</html>

6 管理Cookie及数据存储

6.1 Cookie管理

Cookie是网络访问过程中,由服务端发送给客户端的一小段数据。客户端可持有该数据,并在后续访问该服务端时,方便服务端快速对客户端身份、状态等进行识别。

Web组件提供了WebCookieManager类,用于管理Web组件的Cookie信息。Cookie信息保存在应用沙箱路径下/proc/{pid}/root/data/storage/el2/base/cache/web/Cookiesd的文件中。

下面以setCookie()接口举例,为“www.example.com”设置单个Cookie的值“value=test”。其他Cookie的相关功能及使用

// xxx.ets
import web_webview from '@ohos.web.webview';
import business_error from '@ohos.base';@Entry
@Component
struct WebComponent {controller: web_webview.WebviewController = new web_webview.WebviewController();build() {Column() {Button('setCookie').onClick(() => {try {web_webview.WebCookieManager.setCookie('https://www.example.com', 'value=test');} catch (error) {let e: business_error.BusinessError = error as business_error.BusinessError;console.error(`ErrorCode: ${e.code},  Message: ${e.message}`);}})Web({ src: 'www.example.com', controller: this.controller })}}
}

6.2 缓存与存储管理

在访问网站时,网络资源请求是相对比较耗时的。开发者可以通过CacheDom Storage等手段将资源保存到本地,以提升访问同一网站的速度。

6.2.1 Cache

使用cacheMode()配置页面资源的缓存模式,Web组件为开发者提供四种缓存模式,分别为:

  • Default : 优先使用未过期的缓存,如果缓存不存在,则从网络获取。
  • None : 加载资源使用cache,如果cache中无该资源则从网络中获取。
  • Online : 加载资源不使用cache,全部从网络中获取。
  • Only :只从cache中加载资源。

在下面的示例中,选用缓存设置为None模式。

// xxx.ets
import web_webview from '@ohos.web.webview';@Entry
@Component
struct WebComponent {@State mode: CacheMode = CacheMode.None;controller: web_webview.WebviewController = new web_webview.WebviewController();build() {Column() {Web({ src: 'www.example.com', controller: this.controller }).cacheMode(this.mode)}}
}

同时,为了获取最新资源,开发者可以通过removeCache()接口清除已经缓存的资源,示例代码如下:

// xxx.ets
import web_webview from '@ohos.web.webview';
import business_error from '@ohos.base';@Entry
@Component
struct WebComponent {@State mode: CacheMode = CacheMode.None;controller: web_webview.WebviewController = new web_webview.WebviewController();build() {Column() {Button('removeCache').onClick(() => {try {// 设置为true时同时清除rom和ram中的缓存,设置为false时只清除ram中的缓存this.controller.removeCache(true);} catch (error) {let e: business_error.BusinessError = error as business_error.BusinessError;console.error(`ErrorCode: ${e.code},  Message: ${e.message}`);}})Web({ src: 'www.example.com', controller: this.controller }).cacheMode(this.mode)}}
}

6.2.2 Dom Storage

Dom Storage包含了Session StorageLocal Storage两类。前者为临时数据,其存储与释放跟随会话生命周期;后者为可持久化数据,落盘在应用目录下。两者的数据均通过Key-Value的形式存储,通常在访问需要客户端存储的页面时使用。开发者可以通过Web组件的属性接口domStorageAccess()进行使能配置,示例如下:

// xxx.ets
import web_webview from '@ohos.web.webview';@Entry
@Component
struct WebComponent {controller: web_webview.WebviewController = new web_webview.WebviewController();build() {Column() {Web({ src: 'www.example.com', controller: this.controller }).domStorageAccess(true)}}
}

7 自定义页面请求响应

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

Web网页上发起资源加载请求,应用层收到资源请求消息。应用层构造本地资源响应消息发送给Web内核。Web内核解析应用层响应信息,根据此响应信息进行页面资源加载。

在下面的示例中,Web组件通过拦截页面请求“https://www.example.com/test.html”, 在应用侧代码构建响应资源,实现自定义页面响应场景。

  1. 前端页面index.html代码。
<!DOCTYPE html>
<html>
<head><meta charset="utf-8">
</head>
<body>
<!-- 页面资源请求 -->
<a href="https://www.example.com/test.html">intercept test!</a>
</body>
</html>
  1. 应用侧代码。
// xxx.ets
import web_webview from '@ohos.web.webview';@Entry
@Component
struct WebComponent {controller: web_webview.WebviewController = new web_webview.WebviewController()responseResource: WebResourceResponse = new WebResourceResponse()// 开发者自定义响应数据@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>'build() {Column() {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;})}}
}

8 使用Devtools工具调试前端页面

Web组件支持使用DevTools工具调试前端页面DevTools是一个 Web前端开发调试工具,提供了电脑上调试移动设备前端页面的能力。开发者通过setWebDebuggingAccess()接口开启Web组件前端页面调试能力,利用DevTools工具可以在电脑上调试移动设备上的前端网页,设备需为4.1.0及以上版本。

使用DevTools工具,可以执行以下步骤:

  1. 在应用代码中开启Web调试开关,具体如下:
// xxx.ets
import web_webview from '@ohos.web.webview';@Entry
@Component
struct WebComponent {controller: web_webview.WebviewController = new web_webview.WebviewController();aboutToAppear() {// 配置Web开启调试模式web_webview.WebviewController.setWebDebuggingAccess(true);}build() {Column() {Web({ src: 'www.example.com', controller: this.controller })}}
}
  1. 开启调试功能需要在DevEco Studio应用工程的module.json5文件中增加权限, 具体如下:
"requestPermissions":[{"name" : "ohos.permission.INTERNET"}]
"requestPermissions":[{"name" : "ohos.permission.INTERNET"}]
  1. 将设备连接上电脑,在电脑端配置端口映射,配置方法如下:
//查找 devtools 远程调试所需的 domain socket 名称,该名称与进程号有关,重启调试应用后,需要重复此步骤,以完成端口转发
cat /proc/net/unix | grep devtools
// 添加映射 [pid] 替换成实际的进程id
hdc fport tcp:9222 localabstract:webview_devtools_remote_[pid]
// 查看映射 
hdc fport ls
示例:
hdc shell
cat /proc/net/unix | grep devtools
//显示 webview_devtools_remote_3458
exit
hdc fport tcp:9222 localabstract:webview_devtools_remote_3458
hdc fport ls

在电脑端Chrome浏览器地址栏中输入chrome://inspect/#devices,页面识别到设备后,就可以开始页面调试。调试效果如下:
在这里插入图片描述

参考文献:
[1]OpenHarmoney应用开发文档

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/526264.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

20、电源管理入门之Hypervisor中的电源管理

目录 1. Hypervisor概念介绍 2. 汽车软件中的Hypervisor应用 3. QNX Hypervisor 4. Hypervisor中的多OS通信技术 5. 电源管理相关 参考: 很多时候听说Hypervisor,但是对底层软件技术不了解的人感觉挺神秘。本篇文章简单介绍下Hypervisor的基本概念,另外介绍下电影管理…

个人健康管理系统|基于微信小程序的个人健康管理系统设计与实现(源码+数据库+文档)

个人健康管理小程序目录 目录 基于微信小程序的个人健康管理系统设计与实现 一、前言 二、系统设计 三、系统功能设计 1、用户信息管理 2 运动教程管理 3、公告信息管理 4、论坛信息管理 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最新计算机毕设…

资源哟正版无授权模版源码(含搭建教程)

资源哟 v1.3 – 新增两种首页布局 – 新增幻灯片插件 – 优化深色模式颜色效果 – 优化导航页面左侧栏目跳转效果 – 优化后台辅助插件当前页面打开 源码下载&#xff1a;https://download.csdn.net/download/m0_66047725/88898100 更多资源下载&#xff1a;关注我。

R语言复现:中国Charls数据库一篇现况调查论文的缺失数据填补方法

编者 在临床研究中&#xff0c;数据缺失是不可避免的&#xff0c;甚至没有缺失&#xff0c;数据的真实性都会受到质疑。 那我们该如何应对缺失的数据&#xff1f;放着不管&#xff1f;还是重新开始?不妨试着对缺失值进行填补&#xff0c;简单又高效。毕竟对于统计师来说&#…

签约仪式如何策划和安排流程?如何邀约媒体现场见证报道

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 签约仪式的策划和安排流程&#xff0c;以及邀约媒体现场见证报道&#xff0c;都是确保活动成功和提升影响力的关键环节。以下是一些建议&#xff1a; 签约仪式的策划和安排流程 明确目标…

SDM450核心板_高通SDM450安卓核心板模块性能参数

高通SDM450核心板是基于SDM450移动平台开发的一款高性能核心板。采用领先的14纳米技术&#xff0c;该核心板为高端智能设备提供了卓越的性能和优质的体验。板载2GB16GB的内存(可选配4GB32GB)&#xff0c;双 ISP(图像传感器处理器)支持丰富的照片细节和双摄像头体验&#xff0c;…

计算机网络——计算机网络的性能

计算机网络——计算机网络的性能 速率带宽吞吐量时延时延宽带积往返时间RTT利用率信道利用率网络利用率 我们今天来看看计算机网络的性能。 速率 速率这个很简单&#xff0c;就是数据的传送速率&#xff0c;也称为数据率&#xff0c;或者比特率&#xff0c;单位为bit/s&#…

MySQL主从读写分离之Proxysql(openEuler版)

实验目的&#xff1a; 基于proxysql实现MySQL的主从读写分离。 实验过程&#xff1a; 前期准备&#xff1a; 一共有四台虚拟机&#xff0c;其中三台为配置好的一主两从虚拟机&#xff0c;还有一台干净的虚拟机用来配置proxysql。 主机名地址master192.168.27.137node1192.…

C语言笔记:文件的操作各种文件函数讲解

突然发现自己的C语言文件部分还没有学&#xff0c;赶紧来补一下~~ 1.文件分类 文本文件磁盘文件&#xff08;二进制文件&#xff09;C语言特殊文件标识&#xff1a;stdin&#xff08;标准输入&#xff1a;通指键盘输入&#xff09;&#xff0c;stdout&#xff08;标准输出&am…

【HarmonyOS】ArkTS-联合类型

目录 联合类型实例 联合类型 联合类型是一种灵活的数据类型&#xff0c;它修饰的变量可以存储不同类型的数据。 语法&#xff1a;let 变量: 类型1 | 类型2 | 类型3 值 基于联合类型&#xff0c;变量可存不同类型数据 实例 // 需求&#xff1a;定义一个变量&#xff0c;存放…

Building Systems with the ChatGPT API

Building Systems with the ChatGPT API 本文是 https://www.deeplearning.ai/short-courses/building-systems-with-chatgpt/ 这门课程的学习笔记。 文章目录 Building Systems with the ChatGPT APIWhat you’ll learn in this course Language Models, the Chat Format and…

【编译原理】1、python 实现一个 JSON parser:lex 词法分析、parser 句法分析

文章目录 一、实现 JSON lexer&#xff08;词法解析器&#xff09;二、lex 词法分析2.1 lex string 解析2.2 lex number 解析2.3 lex bool 和 null 解析 三、syntax parser 句法分析3.1 parse array 解析数组3.2 parse object 解析对象 四、封装接口 一、实现 JSON lexer&#…