1# 事件 2<!--Kit: ArkWeb--> 3<!--Subsystem: Web--> 4<!--Owner: @yp99ustc; @aohui; @zourongchun--> 5<!--Designer: @LongLie; @yaomingliu; @zhufenghao--> 6<!--Tester: @ghiker--> 7<!--Adviser: @HelloCrease--> 8 9通用事件仅支持[onAppear](../apis-arkui/arkui-ts/ts-universal-events-show-hide.md#onappear)、[onDisAppear](../apis-arkui/arkui-ts/ts-universal-events-show-hide.md#ondisappear)、[onBlur](../apis-arkui/arkui-ts/ts-universal-focus-event.md#onblur)、[onFocus](../apis-arkui/arkui-ts/ts-universal-focus-event.md#onfocus)、[onDragEnd](../apis-arkui/arkui-ts/ts-universal-events-drag-drop.md#ondragend10)、[onDragEnter](../apis-arkui/arkui-ts/ts-universal-events-drag-drop.md#ondragenter)、[onDragStart](../apis-arkui/arkui-ts/ts-universal-events-drag-drop.md#ondragstart)、[onDragMove](../apis-arkui/arkui-ts/ts-universal-events-drag-drop.md#ondragmove)、[onDragLeave](../apis-arkui/arkui-ts/ts-universal-events-drag-drop.md#ondragleave)、[onDrop](../apis-arkui/arkui-ts/ts-universal-events-drag-drop.md#ondrop)、[onHover](../apis-arkui/arkui-ts/ts-universal-events-hover.md#onhover)、[onMouse](../apis-arkui/arkui-ts/ts-universal-mouse-key.md#onmouse)、[onKeyEvent](../apis-arkui/arkui-ts/ts-universal-events-key.md#onkeyevent)、[onTouch](../apis-arkui/arkui-ts/ts-universal-events-touch.md#ontouch)、[onVisibleAreaChange](../apis-arkui/arkui-ts/ts-universal-component-visible-area-change-event.md#onvisibleareachange)。 10 11> **说明:** 12> 13> - 该组件首批接口从API version 8开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 14> 15> - 示例效果请以真机运行为准,当前DevEco Studio预览器不支持。 16 17## onAlert 18 19onAlert(callback: Callback\<OnAlertEvent, boolean\>) 20 21网页触发alert()告警弹窗时触发回调。 22 23**系统能力:** SystemCapability.Web.Webview.Core 24 25**参数:** 26 27| 参数名 | 类型 | 必填 | 说明 | 28| ------- | --------------------- | ---- | --------------- | 29| callback | Callback\<[OnAlertEvent](./arkts-basic-components-web-i.md#onalertevent12), boolean\> | 是 | 网页触发alert()告警弹窗时触发。<br>返回值boolean。当回调返回true时,应用可以调用自定义弹窗能力(包括确认和取消),并且需要根据用户的确认或取消操作调用JsResult通知Web组件最终确认结果。当回调返回false时,弹窗的处理结果会被视为取消。 | 30 31**示例:** 32 33 ```ts 34 // xxx.ets 35 import { webview } from '@kit.ArkWeb'; 36 37 @Entry 38 @Component 39 struct WebComponent { 40 controller: webview.WebviewController = new webview.WebviewController(); 41 uiContext: UIContext = this.getUIContext(); 42 43 build() { 44 Column() { 45 Web({ src: $rawfile("index.html"), controller: this.controller }) 46 .onAlert((event) => { 47 if (event) { 48 console.info("event.url:" + event.url); 49 console.info("event.message:" + event.message); 50 this.uiContext.showAlertDialog({ 51 title: 'onAlert', 52 message: 'text', 53 primaryButton: { 54 value: 'ok', 55 action: () => { 56 event.result.handleConfirm(); 57 } 58 }, 59 cancel: () => { 60 event.result.handleCancel(); 61 } 62 }) 63 } 64 return true; 65 }) 66 } 67 } 68 } 69 ``` 70 71 加载的html文件。 72 ```html 73 <!--index.html--> 74 <!DOCTYPE html> 75 <html> 76 <head> 77 <meta charset="utf-8" name="viewport" content="width=device-width, initial-scale=1.0"> 78 </head> 79 <body> 80 <h1>WebView onAlert Demo</h1> 81 <button onclick="myFunction()">Click here</button> 82 <script> 83 function myFunction() { 84 alert("Hello World"); 85 } 86 </script> 87 </body> 88 </html> 89 ``` 90 91## onBeforeUnload 92 93onBeforeUnload(callback: Callback\<OnBeforeUnloadEvent, boolean\>) 94 95即将完成页面刷新或关闭当前页面时触发此回调。 96 97> **说明:** 98> 99> - 如果当前Web组件没有得到焦点,刷新或关闭当前页面时onBeforeUnload不会触发。 100 101**系统能力:** SystemCapability.Web.Webview.Core 102 103**参数:** 104 105| 参数名 | 类型 | 必填 | 说明 | 106| ------- | --------------------- | ---- | --------------- | 107| callback | Callback\<[OnBeforeUnloadEvent](./arkts-basic-components-web-i.md#onbeforeunloadevent12), boolean\> | 是 | 即将完成页面刷新或关闭当前页面时触发。<br>返回值boolean。当回调返回true时,应用可以调用自定义弹窗能力(包括确认和取消),并且需要根据用户的确认或取消操作调用JsResult通知Web组件最终是否离开当前页面。当回调返回false时,函数中绘制的自定义弹窗无效。 | 108 109**示例:** 110 111 ```ts 112 // xxx.ets 113 import { webview } from '@kit.ArkWeb'; 114 115 @Entry 116 @Component 117 struct WebComponent { 118 controller: webview.WebviewController = new webview.WebviewController(); 119 uiContext: UIContext = this.getUIContext(); 120 121 build() { 122 Column() { 123 Web({ src: $rawfile("index.html"), controller: this.controller }) 124 .onBeforeUnload((event) => { 125 if (event) { 126 console.info("event.url:" + event.url); 127 console.info("event.message:" + event.message); 128 console.info("event.isReload:" + event?.isReload ?? 'false'); 129 this.uiContext.showAlertDialog({ 130 title: 'onBeforeUnload', 131 message: 'text', 132 primaryButton: { 133 value: 'cancel', 134 action: () => { 135 event.result.handleCancel(); 136 } 137 }, 138 secondaryButton: { 139 value: 'ok', 140 action: () => { 141 event.result.handleConfirm(); 142 } 143 }, 144 cancel: () => { 145 event.result.handleCancel(); 146 } 147 }) 148 } 149 return true; 150 }) 151 } 152 } 153 } 154 ``` 155 156 加载的html文件。 157 ```html 158 <!--index.html--> 159 <!DOCTYPE html> 160 <html> 161 <head> 162 <meta charset="utf-8" name="viewport" content="width=device-width, initial-scale=1.0"> 163 </head> 164 <body onbeforeunload="return myFunction()"> 165 <h1>WebView onBeforeUnload Demo</h1> 166 <a href="https://www.example.com">Click here</a> 167 <script> 168 function myFunction() { 169 return "onBeforeUnload Event"; 170 } 171 </script> 172 </body> 173 </html> 174 ``` 175 176## onConfirm 177 178onConfirm(callback: Callback\<OnConfirmEvent, boolean\>) 179 180网页调用confirm()告警时触发此回调。 181 182**系统能力:** SystemCapability.Web.Webview.Core 183 184**参数:** 185 186| 参数名 | 类型 | 必填 | 说明 | 187| ------- | --------------------- | ---- | --------------- | 188| callback | Callback\<[OnConfirmEvent](./arkts-basic-components-web-i.md#onconfirmevent12), boolean\> | 是 | 网页调用confirm()告警时触发。<br>返回值boolean。当回调返回true时,应用可以调用自定义弹窗能力(包括确认和取消),并且需要根据用户的确认或取消操作调用JsResult通知Web组件最终确认结果。当回调返回false时,弹窗的处理结果会被视为取消。 | 189 190**示例:** 191 192 ```ts 193 // xxx.ets 194 import { webview } from '@kit.ArkWeb'; 195 196 @Entry 197 @Component 198 struct WebComponent { 199 controller: webview.WebviewController = new webview.WebviewController(); 200 uiContext: UIContext = this.getUIContext(); 201 202 build() { 203 Column() { 204 Web({ src: $rawfile("index.html"), controller: this.controller }) 205 .onConfirm((event) => { 206 if (event) { 207 console.info("event.url:" + event.url); 208 console.info("event.message:" + event.message); 209 this.uiContext.showAlertDialog({ 210 title: 'onConfirm', 211 message: 'text', 212 primaryButton: { 213 value: 'cancel', 214 action: () => { 215 event.result.handleCancel(); 216 } 217 }, 218 secondaryButton: { 219 value: 'ok', 220 action: () => { 221 event.result.handleConfirm(); 222 } 223 }, 224 cancel: () => { 225 event.result.handleCancel(); 226 } 227 }) 228 } 229 return true; 230 }) 231 } 232 } 233 } 234 ``` 235 236 加载的html文件。 237 ```html 238 <!--index.html--> 239 <!DOCTYPE html> 240 <html> 241 <head> 242 <meta charset="utf-8" name="viewport" content="width=device-width, initial-scale=1.0"> 243 </head> 244 245 <body> 246 <h1>WebView onConfirm Demo</h1> 247 <button onclick="myFunction()">Click here</button> 248 <p id="demo"></p> 249 <script> 250 function myFunction() { 251 let x; 252 let r = confirm("click button!"); 253 if (r == true) { 254 x = "ok"; 255 } else { 256 x = "cancel"; 257 } 258 document.getElementById("demo").innerHTML = x; 259 } 260 </script> 261 </body> 262 </html> 263 ``` 264 265## onPrompt<sup>9+</sup> 266 267onPrompt(callback: Callback\<OnPromptEvent, boolean\>) 268 269网页调用prompt()告警时触发此回调。 270 271**系统能力:** SystemCapability.Web.Webview.Core 272 273**参数:** 274 275| 参数名 | 类型 | 必填 | 说明 | 276| ------- | --------------------- | ---- | --------------- | 277| callback | Callback\<[OnPromptEvent](./arkts-basic-components-web-i.md#onpromptevent12), boolean\> | 是 | 网页调用prompt()告警时触发。<br>返回值boolean。当回调返回true时,应用可以调用自定义弹窗能力(包括确认、取消和输入),并且需要根据用户的确认或取消操作调用JsResult通知Web组件最终处理结果。当回调返回false时,弹窗的处理结果会被视为取消。 | 278 279**示例:** 280 281 ```ts 282 // xxx.ets 283 import { CustomContentDialog } from '@kit.ArkUI'; 284 import { webview } from '@kit.ArkWeb'; 285 286 @Entry 287 @Component 288 struct WebComponent { 289 @State message: string = 'Hello World'; 290 @State title: string = 'Hello World'; 291 @State result: JsResult | null = null; 292 promptResult: string = ''; 293 webviewController: webview.WebviewController = new webview.WebviewController(); 294 dialogController: CustomDialogController = new CustomDialogController({ 295 builder: CustomContentDialog({ 296 primaryTitle: this.title, 297 contentBuilder: () => { 298 this.buildContent(); 299 }, 300 buttons: [ 301 { 302 value: '取消', 303 buttonStyle: ButtonStyleMode.TEXTUAL, 304 action: () => { 305 console.info('Callback when the button is clicked'); 306 this.result?.handleCancel() 307 } 308 }, 309 { 310 value: '确认', 311 buttonStyle: ButtonStyleMode.TEXTUAL, 312 action: () => { 313 this.result?.handlePromptConfirm(this.promptResult); 314 } 315 } 316 ], 317 }), 318 onWillDismiss: () => { 319 this.result?.handleCancel(); 320 this.dialogController.close(); 321 } 322 }); 323 324 // 自定义弹出框的内容区 325 @Builder 326 buildContent(): void { 327 Column() { 328 Text(this.message) 329 TextInput() 330 .onChange((value) => { 331 this.promptResult = value; 332 }) 333 .defaultFocus(true) 334 } 335 .width('100%') 336 } 337 338 build() { 339 Column() { 340 Web({ src: $rawfile('index.html'), controller: this.webviewController }) 341 .onPrompt((event) => { 342 if (event) { 343 console.info("event.url:" + event.url); 344 console.info("event.message:" + event.message); 345 console.info("event.value:" + event.value); 346 this.title = "来自" + event.url + "的消息"; 347 this.message = event.message; 348 this.promptResult = event.value; 349 this.result = event.result; 350 this.dialogController.open(); 351 } 352 return true; 353 }) 354 } 355 } 356 } 357 ``` 358 359 加载的html文件。 360 ```html 361 <!--index.html--> 362 <!DOCTYPE html> 363 <html> 364 <head> 365 <meta charset="utf-8" name="viewport" content="width=device-width, initial-scale=1.0"> 366 </head> 367 368 <body> 369 <h1>WebView onPrompt Demo</h1> 370 <button onclick="myFunction()">Click here</button> 371 <p id="demo"></p> 372 <script> 373 function myFunction() { 374 let message = prompt("Message info", "Hello World"); 375 if (message != null && message != "") { 376 document.getElementById("demo").innerHTML = message; 377 } 378 } 379 </script> 380 </body> 381 </html> 382 ``` 383 384## onConsole 385 386onConsole(callback: Callback\<OnConsoleEvent, boolean\>) 387 388通知宿主应用JavaScript console消息。 389 390**系统能力:** SystemCapability.Web.Webview.Core 391 392**参数:** 393 394| 参数名 | 类型 | 必填 | 说明 | 395| ------- | --------------------------------- | ---- | --------- | 396| callback | Callback\<[OnConsoleEvent](./arkts-basic-components-web-i.md#onconsoleevent12), boolean\> | 是 | 网页收到JavaScript控制台消息时触发。<br>返回值boolean。当返回true时,该条消息将不会再打印至hilog日志,返回false时仍会打印至hilog日志。 | 397 398**示例:** 399 400 ```ts 401 // xxx.ets 402 import { webview } from '@kit.ArkWeb'; 403 404 @Entry 405 @Component 406 struct WebComponent { 407 controller: webview.WebviewController = new webview.WebviewController(); 408 409 build() { 410 Column() { 411 Button('onconsole message') 412 .onClick(() => { 413 this.controller.runJavaScript('myFunction()'); 414 }) 415 Web({ src: $rawfile('index.html'), controller: this.controller }) 416 .onConsole((event) => { 417 if (event) { 418 console.info('getMessage:' + event.message.getMessage()); 419 console.info('getSourceId:' + event.message.getSourceId()); 420 console.info('getLineNumber:' + event.message.getLineNumber()); 421 console.info('getMessageLevel:' + event.message.getMessageLevel()); 422 } 423 return false; 424 }) 425 } 426 } 427 } 428 ``` 429 430 加载的html文件。 431 ```html 432 <!-- index.html --> 433 <!DOCTYPE html> 434 <html> 435 <body> 436 <script> 437 function myFunction() { 438 console.info("onconsole printf"); 439 } 440 </script> 441 </body> 442 </html> 443 ``` 444 445## onDownloadStart 446 447onDownloadStart(callback: Callback\<OnDownloadStartEvent\>) 448 449通知主应用开始下载一个文件。 450 451**系统能力:** SystemCapability.Web.Webview.Core 452 453**参数:** 454 455| 参数名 | 类型 | 必填 | 说明 | 456| ------------------ | ------ | ---- | ----------------------------------- | 457| callback | Callback\<[OnDownloadStartEvent](./arkts-basic-components-web-i.md#ondownloadstartevent12)\> | 是 | 开始下载时触发。 | 458 459**示例:** 460 461 ```ts 462 // xxx.ets 463 import { webview } from '@kit.ArkWeb'; 464 465 @Entry 466 @Component 467 struct WebComponent { 468 controller: webview.WebviewController = new webview.WebviewController(); 469 470 build() { 471 Column() { 472 Web({ src: 'www.example.com', controller: this.controller }) 473 .onDownloadStart((event) => { 474 if (event) { 475 console.info('url:' + event.url) 476 console.info('userAgent:' + event.userAgent) 477 console.info('contentDisposition:' + event.contentDisposition) 478 console.info('contentLength:' + event.contentLength) 479 console.info('mimetype:' + event.mimetype) 480 } 481 }) 482 } 483 } 484 } 485 ``` 486 487## onErrorReceive 488 489onErrorReceive(callback: Callback\<OnErrorReceiveEvent\>) 490 491网页加载遇到错误时触发该回调。主资源与子资源出错都会回调该接口,可以通过[isMainFrame](./arkts-basic-components-web-WebResourceRequest.md#ismainframe)来判断是否是主资源报错。出于性能考虑,建议此回调中尽量执行简单逻辑。在无网络的情况下,触发此回调。 492 493**系统能力:** SystemCapability.Web.Webview.Core 494 495**参数:** 496 497| 参数名 | 类型 | 必填 | 说明 | 498| ------- | ---------------------------------------- | ---- | --------------- | 499| callback | Callback\<[OnErrorReceiveEvent](./arkts-basic-components-web-i.md#onerrorreceiveevent12)\> | 是 | 网页收到 Web 资源加载错误时触发。 | 500 501**示例:** 502 503 ```ts 504 // xxx.ets 505 import { webview } from '@kit.ArkWeb'; 506 507 @Entry 508 @Component 509 struct WebComponent { 510 controller: webview.WebviewController = new webview.WebviewController(); 511 512 build() { 513 Column() { 514 Web({ src: 'www.example.com', controller: this.controller }) 515 .onErrorReceive((event) => { 516 if (event) { 517 console.info('getErrorInfo:' + event.error.getErrorInfo()); 518 console.info('getErrorCode:' + event.error.getErrorCode()); 519 console.info('url:' + event.request.getRequestUrl()); 520 console.info('isMainFrame:' + event.request.isMainFrame()); 521 console.info('isRedirect:' + event.request.isRedirect()); 522 console.info('isRequestGesture:' + event.request.isRequestGesture()); 523 console.info('getRequestHeader_headerKey:' + event.request.getRequestHeader().toString()); 524 let result = event.request.getRequestHeader(); 525 console.info('The request header result size is ' + result.length); 526 for (let i of result) { 527 console.info('The request header key is : ' + i.headerKey + ', value is : ' + i.headerValue); 528 } 529 } 530 }) 531 } 532 } 533 } 534 ``` 535 536## onHttpErrorReceive 537 538onHttpErrorReceive(callback: Callback\<OnHttpErrorReceiveEvent\>) 539 540网页加载资源遇到的HTTP错误(响应码>=400)时触发该回调。 541 542**系统能力:** SystemCapability.Web.Webview.Core 543 544**参数:** 545 546| 参数名 | 类型 | 必填 | 说明 | 547| -------- | ---------------------------------------- | ---- | ---------- | 548| callback | Callback\<[OnHttpErrorReceiveEvent](./arkts-basic-components-web-i.md#onhttperrorreceiveevent12)\> | 是 | 网页收到加载资源返回HTTP错误码时触发。 | 549 550**示例:** 551 552 ```ts 553 // xxx.ets 554 import { webview } from '@kit.ArkWeb'; 555 556 @Entry 557 @Component 558 struct WebComponent { 559 controller: webview.WebviewController = new webview.WebviewController(); 560 561 build() { 562 Column() { 563 Web({ src: 'www.example.com', controller: this.controller }) 564 .onHttpErrorReceive((event) => { 565 if (event) { 566 console.info('url:' + event.request.getRequestUrl()); 567 console.info('isMainFrame:' + event.request.isMainFrame()); 568 console.info('isRedirect:' + event.request.isRedirect()); 569 console.info('isRequestGesture:' + event.request.isRequestGesture()); 570 console.info('getResponseData:' + event.response.getResponseData()); 571 console.info('getResponseEncoding:' + event.response.getResponseEncoding()); 572 console.info('getResponseMimeType:' + event.response.getResponseMimeType()); 573 console.info('getResponseCode:' + event.response.getResponseCode()); 574 console.info('getReasonMessage:' + event.response.getReasonMessage()); 575 let result = event.request.getRequestHeader(); 576 console.info('The request header result size is ' + result.length); 577 for (let i of result) { 578 console.info('The request header key is : ' + i.headerKey + ' , value is : ' + i.headerValue); 579 } 580 let resph = event.response.getResponseHeader(); 581 console.info('The response header result size is ' + resph.length); 582 for (let i of resph) { 583 console.info('The response header key is : ' + i.headerKey + ' , value is : ' + i.headerValue); 584 } 585 } 586 }) 587 } 588 } 589 } 590 ``` 591 592## onPageBegin 593 594onPageBegin(callback: Callback\<OnPageBeginEvent\>) 595 596网页开始加载时触发该回调,且只在主frame触发,iframe或者frameset的内容加载时不会触发此回调。 597 598**系统能力:** SystemCapability.Web.Webview.Core 599 600**参数:** 601 602| 参数名 | 类型 | 必填 | 说明 | 603| ---- | ------ | ---- | --------- | 604| callback | Callback\<[OnPageBeginEvent](./arkts-basic-components-web-i.md#onpagebeginevent12)\> | 是 | 网页加载开始时触发。 | 605 606**示例:** 607 608 ```ts 609 // xxx.ets 610 import { webview } from '@kit.ArkWeb'; 611 612 @Entry 613 @Component 614 struct WebComponent { 615 controller: webview.WebviewController = new webview.WebviewController(); 616 617 build() { 618 Column() { 619 Web({ src: 'www.example.com', controller: this.controller }) 620 .onPageBegin((event) => { 621 if (event) { 622 console.info('url:' + event.url); 623 } 624 }) 625 } 626 } 627 } 628 ``` 629 630## onPageEnd 631 632onPageEnd(callback: Callback\<OnPageEndEvent\>) 633 634网页加载完成时触发该回调,且只在主frame触发,iframe或者frameset的内容加载时不会触发此回调。 635 636**系统能力:** SystemCapability.Web.Webview.Core 637 638**参数:** 639 640| 参数名 | 类型 | 必填 | 说明 | 641| ---- | ------ | ---- | --------- | 642| callback | Callback\<[OnPageEndEvent](./arkts-basic-components-web-i.md#onpageendevent12)\> | 是 | 网页加载结束时触发。 | 643 644**示例:** 645 646 ```ts 647 // xxx.ets 648 import { webview } from '@kit.ArkWeb'; 649 650 @Entry 651 @Component 652 struct WebComponent { 653 controller: webview.WebviewController = new webview.WebviewController(); 654 655 build() { 656 Column() { 657 Web({ src: 'www.example.com', controller: this.controller }) 658 .onPageEnd((event) => { 659 if (event) { 660 console.info('url:' + event.url); 661 } 662 }) 663 } 664 } 665 } 666 ``` 667 668## onLoadStarted<sup>20+</sup> 669 670onLoadStarted(callback: Callback\<OnLoadStartedEvent\>) 671 672通知宿主应用页面开始加载。此方法在每次主frame加载时调用一次,因此对于包含iframes或frameset的页面,onLoadStarted仅针对主frame调用一次。这意味着当嵌入式frame的内容发生变化时,如点击iframe中的链接或Fragment跳转(即跳转到#fragment_id的导航)等,不会调用onLoadStarted。 673 674**系统能力:** SystemCapability.Web.Webview.Core 675 676**参数:** 677 678| 参数名 | 类型 | 必填 | 说明 | 679| ---- | ------ | ---- | --------- | 680| callback | Callback\<[OnLoadStartedEvent](./arkts-basic-components-web-i.md#onloadstartedevent20)\> | 是 | 网页加载开始时触发。 | 681 682**示例:** 683 684 ```ts 685 // xxx.ets 686 import { webview } from '@kit.ArkWeb'; 687 688 @Entry 689 @Component 690 struct WebComponent { 691 controller: webview.WebviewController = new webview.WebviewController(); 692 693 build() { 694 Column() { 695 Web({ src: 'www.example.com', controller: this.controller }) 696 .onLoadStarted((event) => { 697 if (event) { 698 console.info('url:' + event.url); 699 } 700 }) 701 } 702 } 703 } 704 ``` 705 706## onLoadFinished<sup>20+</sup> 707 708onLoadFinished(callback: Callback\<OnLoadFinishedEvent\>) 709 710通知宿主应用页面已加载完成。此方法仅在主frame加载完成时被调用。对于片段跳转(即导航至#fragment_id),onLoadFinished同样会被触发。 711 712**系统能力:** SystemCapability.Web.Webview.Core 713 714**参数:** 715 716| 参数名 | 类型 | 必填 | 说明 | 717| ---- | ------ | ---- | --------- | 718| callback | Callback\<[OnLoadFinishedEvent](./arkts-basic-components-web-i.md#onloadfinishedevent20)\> | 是 | 网页加载结束时触发。 | 719 720**示例:** 721 722 ```ts 723 // xxx.ets 724 import { webview } from '@kit.ArkWeb'; 725 726 @Entry 727 @Component 728 struct WebComponent { 729 controller: webview.WebviewController = new webview.WebviewController(); 730 731 build() { 732 Column() { 733 Web({ src: 'www.example.com', controller: this.controller }) 734 .onLoadFinished((event) => { 735 if (event) { 736 console.info('url:' + event.url); 737 } 738 }) 739 } 740 } 741 } 742 ``` 743 744## onProgressChange 745 746onProgressChange(callback: Callback\<OnProgressChangeEvent\>) 747 748网页加载进度变化时触发该回调。 749 750**系统能力:** SystemCapability.Web.Webview.Core 751 752**参数:** 753 754| 参数名 | 类型 | 必填 | 说明 | 755| ----------- | ------ | ---- | --------------------- | 756| callback | Callback\<[OnProgressChangeEvent](./arkts-basic-components-web-i.md#onprogresschangeevent12)\> | 是 | 页面加载进度变化时触发的回调。 | 757 758**示例:** 759 760 ```ts 761 // xxx.ets 762 import { webview } from '@kit.ArkWeb'; 763 @Entry 764 @Component 765 struct WebComponent { 766 controller: webview.WebviewController = new webview.WebviewController(); 767 768 build() { 769 Column() { 770 Web({ src: 'www.example.com', controller: this.controller }) 771 .onProgressChange((event) => { 772 if (event) { 773 console.info('newProgress:' + event.newProgress); 774 } 775 }) 776 } 777 } 778 } 779 ``` 780 781## onTitleReceive 782 783onTitleReceive(callback: Callback\<OnTitleReceiveEvent\>) 784 785当页面文档标题`<title>`元素发生变更时,触发回调。若当前页面未显示设置标题,ArkWeb将在加载完成前基于页面的URL生成标题并返回给应用。 786 787**系统能力:** SystemCapability.Web.Webview.Core 788 789**参数:** 790 791| 参数名 | 类型 | 必填 | 说明 | 792| ----- | ------ | ---- | ------------- | 793| callback | Callback\<[OnTitleReceiveEvent](./arkts-basic-components-web-i.md#ontitlereceiveevent12)\> | 是 | 页面文档标题发生变更时触发 | 794 795**示例:** 796 797 ```ts 798 // xxx.ets 799 import { webview } from '@kit.ArkWeb'; 800 801 @Entry 802 @Component 803 struct WebComponent { 804 controller: webview.WebviewController = new webview.WebviewController(); 805 806 build() { 807 Column() { 808 Web({ src: 'www.example.com', controller: this.controller }) 809 .onTitleReceive((event) => { 810 if (event) { 811 console.info('title:' + event.title); 812 console.info('isRealTitle:' + event.isRealTitle); 813 } 814 }) 815 } 816 } 817 } 818 ``` 819 820## onRefreshAccessedHistory 821 822onRefreshAccessedHistory(callback: Callback\<OnRefreshAccessedHistoryEvent\>) 823 824导航完成时触发该回调,用于应用更新其访问的历史链接。 825 826**系统能力:** SystemCapability.Web.Webview.Core 827 828**参数:** 829 830| 参数名 | 类型 | 必填 | 说明 | 831| ----------- | ------- | ---- | ---------------------------------------- | 832| callback | Callback\<[OnRefreshAccessedHistoryEvent](./arkts-basic-components-web-i.md#onrefreshaccessedhistoryevent12)\> | 是 | 在导航完成时触发。 | 833 834**示例:** 835 836 ```ts 837 // xxx.ets 838 import { webview } from '@kit.ArkWeb'; 839 840 @Entry 841 @Component 842 struct WebComponent { 843 controller: webview.WebviewController = new webview.WebviewController(); 844 845 build() { 846 Column() { 847 Web({ src: 'www.example.com', controller: this.controller }) 848 .onRefreshAccessedHistory((event) => { 849 if (event) { 850 console.info('url:' + event.url + ' isReload:' + event.isRefreshed); 851 } 852 }) 853 } 854 } 855 } 856 ``` 857 858## onRenderExited<sup>9+</sup> 859 860onRenderExited(callback: Callback\<OnRenderExitedEvent\>) 861 862应用渲染进程异常退出时触发该回调。 863 864多个Web组件可能共享单个渲染进程,每个受影响的Web组件都会触发该回调。 865 866应用处理该回调时,可以调用绑定的webviewController相关接口来恢复页面。例如[refresh](./arkts-apis-webview-WebviewController.md#refresh)、[loadUrl](./arkts-apis-webview-WebviewController.md#loadurl)等。 867 868组件生命周期回调详情可参考[Web组件的生命周期](../../web/web-event-sequence.md)。 869 870**系统能力:** SystemCapability.Web.Webview.Core 871 872**参数:** 873 874| 参数名 | 类型 | 必填 | 说明 | 875| ---------------- | ---------------------------------------- | ---- | ---------------- | 876| callback | Callback\<[OnRenderExitedEvent](./arkts-basic-components-web-i.md#onrenderexitedevent12)\> | 是 | 渲染过程退出时触发。 | 877 878**示例:** 879 880 ```ts 881 // xxx.ets 882 import { webview } from '@kit.ArkWeb'; 883 884 @Entry 885 @Component 886 struct WebComponent { 887 controller: webview.WebviewController = new webview.WebviewController(); 888 889 build() { 890 Column() { 891 Web({ src: 'chrome://crash/', controller: this.controller }) 892 .onRenderExited((event) => { 893 if (event) { 894 console.info('reason:' + event.renderExitReason); 895 } 896 }) 897 } 898 } 899 } 900 ``` 901## onRenderProcessNotResponding<sup>12+</sup> 902 903onRenderProcessNotResponding(callback: OnRenderProcessNotRespondingCallback) 904 905渲染进程无响应时触发该回调函数。如果Web组件无法处理输入事件,或者无法在合理的时间范围内导航到新的URL,则认为网页进程无响应,并将触发该回调。 906 907只要网页进程一直无响应,此回调仍可能会持续触发,直到网页进程再次响应,此时[onRenderProcessResponding](#onrenderprocessresponding12)将会触发。 908 909应用可以通过WebviewController接口[terminateRenderProcess](./arkts-apis-webview-WebviewController.md#terminaterenderprocess12)来终止关联的渲染进程,这可能会影响同一渲染进程的其他Web组件。 910 911**系统能力:** SystemCapability.Web.Webview.Core 912 913**参数:** 914 915| 参数名 | 类型 | 必填 | 说明 | 916| -------- | ------------------------------------------------------------ | ---- | -------------------------------------- | 917| callback | [OnRenderProcessNotRespondingCallback](./arkts-basic-components-web-t.md#onrenderprocessnotrespondingcallback12) | 是 | 渲染进程无响应时触发的回调。 | 918 919**示例:** 920 921 ```ts 922 // xxx.ets 923 import { webview } from '@kit.ArkWeb'; 924 925 @Entry 926 @Component 927 struct WebComponent { 928 controller: webview.WebviewController = new webview.WebviewController(); 929 930 build() { 931 Column() { 932 Web({ src: 'www.example.com', controller: this.controller }) 933 .onRenderProcessNotResponding((data) => { 934 console.info("onRenderProcessNotResponding: [jsStack]= " + data.jsStack + 935 ", [process]=" + data.pid + ", [reason]=" + data.reason); 936 }) 937 } 938 } 939 } 940 ``` 941 942## onRenderProcessResponding<sup>12+</sup> 943 944onRenderProcessResponding(callback: OnRenderProcessRespondingCallback) 945 946渲染进程由无响应状态变回正常运行状态时触发该回调函数,该回调表明该网页并非真正卡死。 947 948**系统能力:** SystemCapability.Web.Webview.Core 949 950**参数:** 951 952| 参数名 | 类型 | 必填 | 说明 | 953| -------- | ------------------------------------------------------------ | ---- | -------------------------------------- | 954| callback | [OnRenderProcessRespondingCallback](./arkts-basic-components-web-t.md#onrenderprocessrespondingcallback12) | 是 | 渲染进程由无响应状态变回正常运行状态时触发的回调。 | 955 956**示例:** 957 958 ```ts 959 // xxx.ets 960 import { webview } from '@kit.ArkWeb'; 961 962 @Entry 963 @Component 964 struct WebComponent { 965 controller: webview.WebviewController = new webview.WebviewController(); 966 967 build() { 968 Column() { 969 Web({ src: 'www.example.com', controller: this.controller }) 970 .onRenderProcessResponding(() => { 971 console.info("onRenderProcessResponding again"); 972 }) 973 } 974 } 975 } 976 ``` 977 978## onShowFileSelector<sup>9+</sup> 979 980onShowFileSelector(callback: Callback\<OnShowFileSelectorEvent, boolean\>) 981 982调用此函数以处理具有“文件”输入类型的HTML表单。如果不调用此函数或返回false,Web组件会提供默认的“选择文件”处理界面。如果返回true,应用可以自定义“选择文件”的响应行为。 983 984**系统能力:** SystemCapability.Web.Webview.Core 985 986**参数:** 987 988| 参数名 | 类型 | 必填 | 说明 | 989| ------------ | ---------------------------------------- | ---- | ----------------- | 990| callback | Callback\<[OnShowFileSelectorEvent](./arkts-basic-components-web-i.md#onshowfileselectorevent12), boolean\> | 是 | 用于通知Web组件文件选择的结果。<br>返回值boolean。当返回值为true时,用户可以调用系统提供的弹窗能力。当返回值为false时,函数中绘制的自定义弹窗无效。 | 991 992**示例:** 993 9941. 拉起文件选择器。 995 996 ```ts 997 // xxx.ets 998 import { webview } from '@kit.ArkWeb'; 999 import { picker } from '@kit.CoreFileKit'; 1000 import { BusinessError } from '@kit.BasicServicesKit'; 1001 1002 @Entry 1003 @Component 1004 struct WebComponent { 1005 controller: webview.WebviewController = new webview.WebviewController() 1006 1007 build() { 1008 Column() { 1009 Web({ src: $rawfile('index.html'), controller: this.controller }) 1010 .onShowFileSelector((event) => { 1011 console.info('MyFileUploader onShowFileSelector invoked') 1012 const documentSelectOptions = new picker.DocumentSelectOptions(); 1013 let uri: string | null = null; 1014 const documentViewPicker = new picker.DocumentViewPicker(); 1015 documentViewPicker.select(documentSelectOptions).then((documentSelectResult) => { 1016 uri = documentSelectResult[0]; 1017 console.info('documentViewPicker.select to file succeed and uri is:' + uri); 1018 if (event) { 1019 event.result.handleFileList([uri]); 1020 } 1021 }).catch((err: BusinessError) => { 1022 console.error(`Invoke documentViewPicker.select failed, code is ${err.code}, message is ${err.message}`); 1023 }) 1024 return true; 1025 }) 1026 } 1027 } 1028 } 1029 ``` 1030 10312. 拉起图库选择器。 1032 1033 ```ts 1034 // xxx.ets 1035 import { webview } from '@kit.ArkWeb'; 1036 import { picker } from '@kit.CoreFileKit'; 1037 import { photoAccessHelper } from '@kit.MediaLibraryKit'; 1038 1039 @Entry 1040 @Component 1041 struct WebComponent { 1042 controller: webview.WebviewController = new webview.WebviewController(); 1043 1044 async selectFile(result: FileSelectorResult): Promise<void> { 1045 let photoSelectOptions = new photoAccessHelper.PhotoSelectOptions(); 1046 let photoPicker = new photoAccessHelper.PhotoViewPicker(); 1047 // 过滤选择媒体文件类型为IMAGE_VIDEO 1048 photoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_VIDEO_TYPE; 1049 // 设置最大选择数量 1050 photoSelectOptions.maxSelectNumber = 5; 1051 let chooseFile: photoAccessHelper.PhotoSelectResult = await photoPicker.select(photoSelectOptions); 1052 // 获取选择的文件列表 1053 result.handleFileList(chooseFile.photoUris); 1054 } 1055 1056 build() { 1057 Column() { 1058 Web({ src: $rawfile('index.html'), controller: this.controller }) 1059 .onShowFileSelector((event) => { 1060 if (event) { 1061 this.selectFile(event.result); 1062 } 1063 return true; 1064 }) 1065 } 1066 } 1067 } 1068 ``` 1069 10703. 拉起相机选择器。 1071 1072 ```ts 1073 // xxx.ets 1074 import { webview } from '@kit.ArkWeb'; 1075 import { cameraPicker, camera } from '@kit.CameraKit'; 1076 import { BusinessError } from '@kit.BasicServicesKit'; 1077 import { common } from '@kit.AbilityKit'; 1078 1079 async function openCamera(callback: Callback<string>, uiContext: UIContext) { 1080 let mContext = uiContext.getHostContext() as common.Context; 1081 try { 1082 let pickerProfile: cameraPicker.PickerProfile = { 1083 cameraPosition: camera.CameraPosition.CAMERA_POSITION_BACK 1084 }; 1085 let pickerResult: cameraPicker.PickerResult = await cameraPicker.pick(mContext, 1086 [cameraPicker.PickerMediaType.PHOTO, cameraPicker.PickerMediaType.VIDEO], pickerProfile); 1087 callback(pickerResult.resultUri); 1088 } catch (error) { 1089 let err = error as BusinessError; 1090 console.error(`the pick call failed. error code: ${err.code}`); 1091 } 1092 } 1093 1094 @Entry 1095 @Component 1096 struct WebComponent { 1097 controller: webview.WebviewController = new webview.WebviewController(); 1098 1099 build() { 1100 Column() { 1101 Web({ src: $rawfile('index.html'), controller: this.controller }) 1102 .onShowFileSelector((event) => { 1103 openCamera((result) => { 1104 if (event) { 1105 console.info('Title is ' + event.fileSelector.getTitle()); 1106 console.info('Mode is ' + event.fileSelector.getMode()); 1107 console.info('Accept types are ' + event.fileSelector.getAcceptType()); 1108 console.info('Capture is ' + event.fileSelector.isCapture()); 1109 console.info('Mime types are ' + event.fileSelector.getMimeTypes()); 1110 event.result.handleFileList([result]); 1111 } 1112 }, this.getUIContext()) 1113 return true; 1114 }) 1115 } 1116 } 1117 } 1118 ``` 1119 1120 加载的html文件。 1121 ```html 1122 <!DOCTYPE html> 1123 <html> 1124 <head> 1125 <meta charset="utf-8" name="viewport" content="width=device-width, initial-scale=1.0"> 1126 </head> 1127 <body> 1128 <form id="upload-form" enctype="multipart/form-data"> 1129 <input type="file" id="upload" name="upload" accept="image/*, video/*"/> 1130 </form> 1131 </body> 1132 </html> 1133 ``` 1134 1135## onResourceLoad<sup>9+</sup> 1136 1137onResourceLoad(callback: Callback\<OnResourceLoadEvent\>) 1138 1139通知Web组件所加载的资源文件url信息。 1140 1141**系统能力:** SystemCapability.Web.Webview.Core 1142 1143**参数:** 1144 1145| 参数名 | 类型 | 必填 | 说明 | 1146| ------ | ------ | ---- | --------------------- | 1147| callback | Callback\<[OnResourceLoadEvent](./arkts-basic-components-web-i.md#onresourceloadevent12)\> | 是 | 加载url时触发。 | 1148 1149**示例:** 1150 1151 ```ts 1152 // xxx.ets 1153 import { webview } from '@kit.ArkWeb'; 1154 1155 @Entry 1156 @Component 1157 struct WebComponent { 1158 controller: webview.WebviewController = new webview.WebviewController(); 1159 1160 build() { 1161 Column() { 1162 Web({ src: 'www.example.com', controller: this.controller }) 1163 .onResourceLoad((event) => { 1164 console.info('onResourceLoad: ' + event.url); 1165 }) 1166 } 1167 } 1168 } 1169 ``` 1170 1171## onScaleChange<sup>9+</sup> 1172 1173onScaleChange(callback: Callback\<OnScaleChangeEvent\>) 1174 1175当页面显示比例发生变化时,触发该回调。 1176 1177**系统能力:** SystemCapability.Web.Webview.Core 1178 1179**参数:** 1180 1181| 参数名 | 类型 | 必填 | 说明 | 1182| ------ | ------ | ---- | --------------------- | 1183| callback | Callback\<[OnScaleChangeEvent](./arkts-basic-components-web-i.md#onscalechangeevent12)\> | 是 | 当页面显示比例发生变化时,触发该回调。 | 1184 1185**示例:** 1186 1187 ```ts 1188 // xxx.ets 1189 import { webview } from '@kit.ArkWeb'; 1190 1191 @Entry 1192 @Component 1193 struct WebComponent { 1194 controller: webview.WebviewController = new webview.WebviewController(); 1195 1196 build() { 1197 Column() { 1198 Web({ src: 'www.example.com', controller: this.controller }) 1199 .onScaleChange((event) => { 1200 console.info('onScaleChange changed from ' + event.oldScale + ' to ' + event.newScale); 1201 }) 1202 } 1203 } 1204 } 1205 ``` 1206 1207## onInterceptRequest<sup>9+</sup> 1208 1209onInterceptRequest(callback: Callback<OnInterceptRequestEvent, WebResourceResponse>) 1210 1211当Web组件加载URL之前触发该回调,用于拦截URL并返回响应数据。`onInterceptRequest`可拦截所有跳转请求并返回响应数据,但无法访问POST请求体(Body)内容,且不支持分片缓冲(buffer)类型数据获取。此类场景需改用[WebSchemeHandler](./arkts-apis-webview-WebSchemeHandler.md)实现,依据具体业务需求进行判断。 1212 1213**系统能力:** SystemCapability.Web.Webview.Core 1214 1215**参数:** 1216 1217| 参数名 | 类型 | 必填 | 说明 | 1218| ------ | ------ | ---- | --------------------- | 1219| callback | Callback\<[OnInterceptRequestEvent](./arkts-basic-components-web-i.md#oninterceptrequestevent12), [WebResourceResponse](./arkts-basic-components-web-WebResourceResponse.md)\> | 是 | 当Web组件加载url之前触发。<br>返回值[WebResourceResponse](./arkts-basic-components-web-WebResourceResponse.md)。返回响应数据则按照响应数据加载,无响应数据则返回null表示按照原来的方式加载。 | 1220 1221**示例:** 1222 1223 ```ts 1224 // xxx.ets 1225 import { webview } from '@kit.ArkWeb'; 1226 1227 @Entry 1228 @Component 1229 struct WebComponent { 1230 controller: webview.WebviewController = new webview.WebviewController(); 1231 responseWeb: WebResourceResponse = new WebResourceResponse(); 1232 heads: Header[] = new Array(); 1233 webData: string = "<!DOCTYPE html>\n" + 1234 "<html>\n" + 1235 "<head>\n" + 1236 "<title>intercept test</title>\n" + 1237 "</head>\n" + 1238 "<body>\n" + 1239 "<h1>intercept test</h1>\n" + 1240 "</body>\n" + 1241 "</html>"; 1242 1243 build() { 1244 Column() { 1245 Web({ src: 'www.example.com', controller: this.controller }) 1246 .onInterceptRequest((event) => { 1247 if (event) { 1248 console.info('url:' + event.request.getRequestUrl()); 1249 } 1250 let head1: Header = { 1251 headerKey: "Connection", 1252 headerValue: "keep-alive" 1253 } 1254 let head2: Header = { 1255 headerKey: "Cache-Control", 1256 headerValue: "no-cache" 1257 } 1258 // 将新元素追加到数组的末尾,并返回数组的新长度。 1259 let length = this.heads.push(head1); 1260 length = this.heads.push(head2); 1261 console.info('The response header result length is :' + length); 1262 const promise: Promise<String> = new Promise((resolve: Function, reject: Function) => { 1263 this.responseWeb.setResponseHeader(this.heads); 1264 this.responseWeb.setResponseData(this.webData); 1265 this.responseWeb.setResponseEncoding('utf-8'); 1266 this.responseWeb.setResponseMimeType('text/html'); 1267 this.responseWeb.setResponseCode(200); 1268 this.responseWeb.setReasonMessage('OK'); 1269 resolve("success"); 1270 }) 1271 promise.then(() => { 1272 console.info("prepare response ready"); 1273 this.responseWeb.setResponseIsReady(true); 1274 }) 1275 this.responseWeb.setResponseIsReady(false); 1276 return this.responseWeb; 1277 }) 1278 } 1279 } 1280 } 1281 ``` 1282 1283## onHttpAuthRequest<sup>9+</sup> 1284 1285onHttpAuthRequest(callback: Callback\<OnHttpAuthRequestEvent, boolean\>) 1286 1287通知收到http auth认证请求。 1288 1289**系统能力:** SystemCapability.Web.Webview.Core 1290 1291**参数:** 1292 1293| 参数名 | 类型 | 必填 | 说明 | 1294| ------ | ------ | ---- | --------------------- | 1295| callback | Callback\<[OnHttpAuthRequestEvent](./arkts-basic-components-web-i.md#onhttpauthrequestevent12), boolean\> | 是 | 当浏览器需要用户的凭据时触发。<br>返回值boolean。返回ture表示http auth认证成功,返回false表示http auth认证失败。 | 1296 1297**示例:** 1298 1299 ```ts 1300 // xxx.ets 1301 import { webview } from '@kit.ArkWeb'; 1302 1303 @Entry 1304 @Component 1305 struct WebComponent { 1306 controller: webview.WebviewController = new webview.WebviewController(); 1307 uiContext: UIContext = this.getUIContext(); 1308 httpAuth: boolean = false; 1309 1310 build() { 1311 Column() { 1312 Web({ src: 'www.example.com', controller: this.controller }) 1313 .onHttpAuthRequest((event) => { 1314 if (event) { 1315 this.uiContext.showAlertDialog({ 1316 title: 'onHttpAuthRequest', 1317 message: 'text', 1318 primaryButton: { 1319 value: 'cancel', 1320 action: () => { 1321 event.handler.cancel(); 1322 } 1323 }, 1324 secondaryButton: { 1325 value: 'ok', 1326 action: () => { 1327 this.httpAuth = event.handler.isHttpAuthInfoSaved(); 1328 if (this.httpAuth == false) { 1329 webview.WebDataBase.saveHttpAuthCredentials( 1330 event.host, 1331 event.realm, 1332 "2222", 1333 "2222" 1334 ) 1335 event.handler.cancel(); 1336 } 1337 } 1338 }, 1339 cancel: () => { 1340 event.handler.cancel(); 1341 } 1342 }) 1343 } 1344 return true; 1345 }) 1346 } 1347 } 1348 } 1349 ``` 1350## onSslErrorEventReceive<sup>9+</sup> 1351 1352onSslErrorEventReceive(callback: Callback\<OnSslErrorEventReceiveEvent\>) 1353 1354通知用户加载资源时发生SSL错误,只支持主资源。 1355如果需要支持子资源,请使用[OnSslErrorEvent](./arkts-basic-components-web-events.md#onsslerrorevent12)接口。 1356 1357> **说明:** 1358> 1359> - 主资源:浏览器加载网页的入口文件,通常是HTML文档。 1360> - 子资源:主资源中引用的依赖文件,由主资源解析过程中遇到特定标签时触发加载。 1361 1362**系统能力:** SystemCapability.Web.Webview.Core 1363 1364**参数:** 1365 1366| 参数名 | 类型 | 必填 | 说明 | 1367| ------ | ------ | ---- | --------------------- | 1368| callback | Callback\<[OnSslErrorEventReceiveEvent](./arkts-basic-components-web-i.md#onsslerroreventreceiveevent12)\> | 是 | 当网页收到SSL错误时触发。 | 1369 1370**示例:** 1371 1372 ```ts 1373 // xxx.ets 1374 import { webview } from '@kit.ArkWeb'; 1375 import { cert } from '@kit.DeviceCertificateKit'; 1376 1377 function LogCertInfo(certChainData : Array<Uint8Array> | undefined) { 1378 if (!(certChainData instanceof Array)) { 1379 console.info('failed, cert chain data type is not array'); 1380 return; 1381 } 1382 1383 for (let i = 0; i < certChainData.length; i++) { 1384 let encodeBlobData: cert.EncodingBlob = { 1385 data: certChainData[i], 1386 encodingFormat: cert.EncodingFormat.FORMAT_DER 1387 } 1388 cert.createX509Cert(encodeBlobData, (error, x509Cert) => { 1389 if (error) { 1390 console.error('Index : ' + i + ',createX509Cert failed, errCode: ' + error.code + ', errMsg: ' + error.message); 1391 } else { 1392 console.info('createX509Cert success'); 1393 console.info(ParseX509CertInfo(x509Cert)); 1394 } 1395 }); 1396 } 1397 return; 1398 } 1399 1400 function Uint8ArrayToString(dataArray: Uint8Array) { 1401 let dataString = ''; 1402 for (let i = 0; i < dataArray.length; i++) { 1403 dataString += String.fromCharCode(dataArray[i]); 1404 } 1405 return dataString; 1406 } 1407 1408 function ParseX509CertInfo(x509Cert: cert.X509Cert) { 1409 let res: string = 'getCertificate success, ' 1410 + 'issuer name = ' 1411 + Uint8ArrayToString(x509Cert.getIssuerName().data) + ', subject name = ' 1412 + Uint8ArrayToString(x509Cert.getSubjectName().data) + ', valid start = ' 1413 + x509Cert.getNotBeforeTime() 1414 + ', valid end = ' + x509Cert.getNotAfterTime(); 1415 return res; 1416 } 1417 1418 @Entry 1419 @Component 1420 struct WebComponent { 1421 controller: webview.WebviewController = new webview.WebviewController(); 1422 uiContext: UIContext = this.getUIContext(); 1423 1424 build() { 1425 Column() { 1426 Web({ src: 'www.example.com', controller: this.controller }) 1427 .onSslErrorEventReceive((event) => { 1428 LogCertInfo(event.certChainData); 1429 this.uiContext.showAlertDialog({ 1430 title: 'onSslErrorEventReceive', 1431 message: 'text', 1432 primaryButton: { 1433 value: 'confirm', 1434 action: () => { 1435 event.handler.handleConfirm(); 1436 } 1437 }, 1438 secondaryButton: { 1439 value: 'cancel', 1440 action: () => { 1441 event.handler.handleCancel(); 1442 } 1443 }, 1444 cancel: () => { 1445 event.handler.handleCancel(); 1446 } 1447 }) 1448 }) 1449 } 1450 } 1451 } 1452 ``` 1453 1454## onSslErrorEvent<sup>12+</sup> 1455 1456onSslErrorEvent(callback: OnSslErrorEventCallback) 1457 1458通知用户加载资源(主资源+子资源)时发生SSL错误,如果只想处理主资源的SSL错误,请用[isMainFrame](./arkts-basic-components-web-WebResourceRequest.md#ismainframe)字段进行区分。 1459 1460> **说明:** 1461> 1462> - 主资源:浏览器加载网页的入口文件,通常是HTML文档。 1463> - 子资源:主资源中引用的依赖文件,由主资源解析过程中遇到特定标签时触发加载。 1464 1465**系统能力:** SystemCapability.Web.Webview.Core 1466 1467**参数:** 1468 1469| 参数名 | 类型 | 必填 | 说明 | 1470| ------ | ------ | ---- | --------------------- | 1471| callback | [OnSslErrorEventCallback](./arkts-basic-components-web-t.md#onsslerroreventcallback12) | 是 | 通知用户加载资源时发生SSL错误。 | 1472 1473**示例:** 1474 1475 ```ts 1476 // xxx.ets 1477 import { webview } from '@kit.ArkWeb'; 1478 import { cert } from '@kit.DeviceCertificateKit'; 1479 1480 function LogCertInfo(certChainData : Array<Uint8Array> | undefined) { 1481 if (!(certChainData instanceof Array)) { 1482 console.info('failed, cert chain data type is not array'); 1483 return; 1484 } 1485 1486 for (let i = 0; i < certChainData.length; i++) { 1487 let encodeBlobData: cert.EncodingBlob = { 1488 data: certChainData[i], 1489 encodingFormat: cert.EncodingFormat.FORMAT_DER 1490 } 1491 cert.createX509Cert(encodeBlobData, (error, x509Cert) => { 1492 if (error) { 1493 console.error('Index : ' + i + ',createX509Cert failed, errCode: ' + error.code + ', errMsg: ' + error.message); 1494 } else { 1495 console.info('createX509Cert success'); 1496 console.info(ParseX509CertInfo(x509Cert)); 1497 } 1498 }); 1499 } 1500 return; 1501 } 1502 1503 function Uint8ArrayToString(dataArray: Uint8Array) { 1504 let dataString = ''; 1505 for (let i = 0; i < dataArray.length; i++) { 1506 dataString += String.fromCharCode(dataArray[i]); 1507 } 1508 return dataString; 1509 } 1510 1511 function ParseX509CertInfo(x509Cert: cert.X509Cert) { 1512 let res: string = 'getCertificate success, ' 1513 + 'issuer name = ' 1514 + Uint8ArrayToString(x509Cert.getIssuerName().data) + ', subject name = ' 1515 + Uint8ArrayToString(x509Cert.getSubjectName().data) + ', valid start = ' 1516 + x509Cert.getNotBeforeTime() 1517 + ', valid end = ' + x509Cert.getNotAfterTime(); 1518 return res; 1519 } 1520 1521 @Entry 1522 @Component 1523 struct WebComponent { 1524 controller: webview.WebviewController = new webview.WebviewController(); 1525 uiContext: UIContext = this.getUIContext(); 1526 1527 build() { 1528 Column() { 1529 Web({ src: 'www.example.com', controller: this.controller }) 1530 .onSslErrorEvent((event: SslErrorEvent) => { 1531 console.info("onSslErrorEvent url: " + event.url); 1532 console.info("onSslErrorEvent error: " + event.error); 1533 console.info("onSslErrorEvent originalUrl: " + event.originalUrl); 1534 console.info("onSslErrorEvent referrer: " + event.referrer); 1535 console.info("onSslErrorEvent isFatalError: " + event.isFatalError); 1536 console.info("onSslErrorEvent isMainFrame: " + event.isMainFrame); 1537 LogCertInfo(event.certChainData); 1538 this.uiContext.showAlertDialog({ 1539 title: 'onSslErrorEvent', 1540 message: 'text', 1541 primaryButton: { 1542 value: 'confirm', 1543 action: () => { 1544 event.handler.handleConfirm(); 1545 } 1546 }, 1547 secondaryButton: { 1548 value: 'cancel', 1549 action: () => { 1550 // true表示停止加载页面,停留在当前页面,使用false表示继续加载页面,并展示错误页面 1551 event.handler.handleCancel(true); 1552 } 1553 }, 1554 cancel: () => { 1555 event.handler.handleCancel(); 1556 } 1557 }) 1558 }) 1559 } 1560 } 1561 } 1562 ``` 1563 1564## onClientAuthenticationRequest<sup>9+</sup> 1565 1566onClientAuthenticationRequest(callback: Callback\<OnClientAuthenticationEvent\>) 1567 1568通知用户收到SSL客户端证书请求事件。 1569 1570**系统能力:** SystemCapability.Web.Webview.Core 1571 1572**参数:** 1573 1574| 参数名 | 类型 | 必填 | 说明 | 1575| ------ | ------ | ---- | --------------------- | 1576| callback | Callback\<[OnClientAuthenticationEvent](./arkts-basic-components-web-i.md#onclientauthenticationevent12)\> | 是 | 当需要用户提供的SSL客户端证书时触发的回调。 | 1577 1578 **示例:** 1579 1580安装私有凭证以实现双向认证。 1581 1582```ts 1583// xxx.ets 1584import { webview } from '@kit.ArkWeb'; 1585import { common } from '@kit.AbilityKit'; 1586import { certificateManager } from '@kit.DeviceCertificateKit'; 1587import { promptAction } from '@kit.ArkUI'; 1588import { BusinessError } from '@kit.BasicServicesKit'; 1589 1590@Entry 1591@Component 1592struct Index { 1593 controller: WebviewController = new webview.WebviewController(); 1594 uiContext : UIContext = this.getUIContext(); 1595 context : Context | undefined = this.uiContext.getHostContext() as common.UIAbilityContext; 1596 uri: string = '' 1597 1598 aboutToAppear(): void { 1599 webview.WebviewController.setRenderProcessMode(webview.RenderProcessMode.MULTIPLE) 1600 } 1601 1602 build() { 1603 Column() { 1604 Button("installPrivateCertificate").onClick(() => { 1605 if (!this.context) { 1606 return; 1607 } 1608 1609 //注:badssl.com-client.p12需要替换为实际使用的证书文件 1610 let value: Uint8Array = this.context.resourceManager.getRawFileContentSync("badssl.com-client.p12"); 1611 certificateManager.installPrivateCertificate(value, 'badssl.com', "1", 1612 async (err: BusinessError, data: certificateManager.CMResult) => { 1613 console.info(`installPrivateCertificate, uri==========${JSON.stringify(data.uri)}`) 1614 if (!err && data.uri) { 1615 this.uri = data.uri; 1616 } 1617 }); 1618 }) 1619 Button('加载需要客户端SSL证书的网站') 1620 .onClick(() => { 1621 this.controller.loadUrl("https://client.badssl.com") 1622 }) 1623 Web({ 1624 src: "https://www.bing.com/", 1625 controller: this.controller, 1626 }).domStorageAccess(true) 1627 .fileAccess(true) 1628 .onPageBegin(event => { 1629 console.info("extensions onpagebegin url " + event.url); 1630 }) 1631 .onClientAuthenticationRequest((event) => { 1632 console.info("onClientAuthenticationRequest "); 1633 event.handler.confirm(this.uri); 1634 return true; 1635 }) 1636 .onSslErrorEventReceive(e => { 1637 console.info(`onSslErrorEventReceive->${e.error.toString()}`); 1638 }) 1639 .onErrorReceive((event) => { 1640 if (event) { 1641 this.getUIContext().getPromptAction().showToast({ 1642 message: `ErrorCode: ${event.error.getErrorCode()}, ErrorInfo: ${event.error.getErrorInfo()}`, 1643 alignment: Alignment.Center 1644 }) 1645 console.info('getErrorInfo:' + event.error.getErrorInfo()); 1646 console.info('getErrorCode:' + event.error.getErrorCode()); 1647 console.info('url:' + event.request.getRequestUrl()); 1648 } 1649 }) 1650 .onTitleReceive(event => { 1651 console.info("title received " + event.title); 1652 }) 1653 1654 } 1655 } 1656} 1657``` 1658 1659对接证书管理,实现双向认证功能。 1660 16611. 构造 `GlobalContext` 单例对象。 1662 ```ts 1663 // GlobalContext.ets 1664 export class GlobalContext { 1665 private constructor() {} 1666 private static instance: GlobalContext; 1667 private _objects = new Map<string, Object>(); 1668 1669 public static getContext(): GlobalContext { 1670 if (!GlobalContext.instance) { 1671 GlobalContext.instance = new GlobalContext(); 1672 } 1673 return GlobalContext.instance; 1674 } 1675 1676 getObject(value: string): Object | undefined { 1677 return this._objects.get(value); 1678 } 1679 1680 setObject(key: string, objectClass: Object): void { 1681 this._objects.set(key, objectClass); 1682 } 1683 } 1684 ``` 1685 16862. 构造 `CertManagerService` 对象以对接证书管理。 1687<!--code_no_check--> 1688 ```ts 1689 // CertMgrService.ets 1690 import { bundleManager, common, Want } from "@kit.AbilityKit"; 1691 import { BusinessError } from "@kit.BasicServicesKit"; 1692 import { GlobalContext } from './GlobalContext'; 1693 1694 export default class CertManagerService { 1695 private static sInstance: CertManagerService; 1696 private authUri = ""; 1697 private appUid = ""; 1698 1699 public static getInstance(): CertManagerService { 1700 if (CertManagerService.sInstance == null) { 1701 CertManagerService.sInstance = new CertManagerService(); 1702 } 1703 return CertManagerService.sInstance; 1704 } 1705 1706 async grantAppPm(): Promise<string> { 1707 let bundleFlags = bundleManager.BundleFlag.GET_BUNDLE_INFO_DEFAULT | bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION; 1708 // 注:com.example.myapplication需要写实际应用名称 1709 try { 1710 const data = await bundleManager.getBundleInfoForSelf(bundleFlags) 1711 .catch((err: BusinessError) => { 1712 console.error('getBundleInfoForSelf failed. Cause: %{public}s', err.message); 1713 return null; 1714 }); 1715 this.appUid = data?.appInfo?.uid?.toString() ?? ''; 1716 console.info('getBundleInfoForSelf successfully. Data: %{public}s', JSON.stringify(data)); 1717 } catch (err) { 1718 let message = (err as BusinessError).message; 1719 console.error('getBundleInfoForSelf failed: %{public}s', message); 1720 } 1721 1722 // 注:需要在MainAbility.ts文件的onCreate函数里添加GlobalContext.getContext().setObject("AbilityContext", this.context) 1723 let abilityContext = GlobalContext.getContext().getObject("AbilityContext") as common.UIAbilityContext; 1724 await abilityContext.startAbilityForResult( 1725 { 1726 bundleName: "com.ohos.certmanager", 1727 abilityName: "MainAbility", 1728 uri: "requestAuthorize", 1729 parameters: { 1730 appUid: this.appUid, // 传入申请应用的appUid 1731 } 1732 } as Want) 1733 .then((data: common.AbilityResult) => { 1734 if (!data.resultCode && data.want) { 1735 if (data.want.parameters) { 1736 this.authUri = data.want.parameters.authUri as string; // 授权成功后获取返回的authUri 1737 } 1738 } 1739 }) 1740 return this.authUri; 1741 } 1742 } 1743 ``` 17443. 实现双向认证功能。 1745<!--code_no_check--> 1746 ```ts 1747 import { webview } from '@kit.ArkWeb'; 1748 import CertManagerService from './CertMgrService'; 1749 import { promptAction } from '@kit.ArkUI'; 1750 1751 @Entry 1752 @Component 1753 struct Index { 1754 controller: WebviewController = new webview.WebviewController(); 1755 certManager = CertManagerService.getInstance(); 1756 1757 aboutToAppear(): void { 1758 webview.WebviewController.setRenderProcessMode(webview.RenderProcessMode.MULTIPLE) 1759 } 1760 1761 build() { 1762 Column() { 1763 Button('加载需要客户端SSL证书的网站') 1764 .onClick(() => { 1765 this.controller.loadUrl("https://client.badssl.com") 1766 }) 1767 Web({ 1768 src: "https://www.bing.com/", 1769 controller: this.controller, 1770 }).domStorageAccess(true) 1771 .fileAccess(true) 1772 .onPageBegin(event => { 1773 console.info("extensions onpagebegin url " + event.url); 1774 }) 1775 .onClientAuthenticationRequest((event) => { 1776 console.info("onClientAuthenticationRequest "); 1777 1778 this.certManager.grantAppPm().then(result => { 1779 console.info(`grantAppPm, URI==========${result}`); 1780 event.handler.confirm(result); 1781 }) 1782 return true; 1783 }) 1784 .onSslErrorEventReceive(e => { 1785 console.info(`onSslErrorEventReceive->${e.error.toString()}`); 1786 }) 1787 .onErrorReceive((event) => { 1788 if (event) { 1789 this.getUIContext().getPromptAction().showToast({ 1790 message: `ErrorCode: ${event.error.getErrorCode()}, ErrorInfo: ${event.error.getErrorInfo()}`, 1791 alignment: Alignment.Center 1792 }) 1793 console.info('getErrorInfo:' + event.error.getErrorInfo()); 1794 console.info('getErrorCode:' + event.error.getErrorCode()); 1795 console.info('url:' + event.request.getRequestUrl()); 1796 } 1797 }) 1798 .onTitleReceive(event => { 1799 console.info("title received " + event.title); 1800 }) 1801 1802 } 1803 } 1804 } 1805 ``` 1806 1807## onPermissionRequest<sup>9+</sup> 1808 1809onPermissionRequest(callback: Callback\<OnPermissionRequestEvent\>) 1810 1811通知收到获取权限请求,需配置"ohos.permission.CAMERA"、"ohos.permission.MICROPHONE"权限。 1812 1813**系统能力:** SystemCapability.Web.Webview.Core 1814 1815**参数:** 1816 1817| 参数名 | 类型 | 必填 | 说明 | 1818| ------ | ------ | ---- | --------------------- | 1819| callback | Callback\<[OnPermissionRequestEvent](./arkts-basic-components-web-i.md#onpermissionrequestevent12)\> | 是 | 通知收到获取权限请求触发。 | 1820 1821**示例:** 1822 1823 ```ts 1824 // xxx.ets 1825 import { webview } from '@kit.ArkWeb'; 1826 import { BusinessError } from '@kit.BasicServicesKit'; 1827 import { abilityAccessCtrl } from '@kit.AbilityKit'; 1828 1829 @Entry 1830 @Component 1831 struct WebComponent { 1832 controller: webview.WebviewController = new webview.WebviewController(); 1833 uiContext: UIContext = this.getUIContext(); 1834 1835 aboutToAppear() { 1836 // 配置Web开启调试模式 1837 webview.WebviewController.setWebDebuggingAccess(true); 1838 let atManager = abilityAccessCtrl.createAtManager(); 1839 atManager.requestPermissionsFromUser(this.uiContext.getHostContext(), ['ohos.permission.CAMERA', 'ohos.permission.MICROPHONE']) 1840 .then((data) => { 1841 console.info('data:' + JSON.stringify(data)); 1842 console.info('data permissions:' + data.permissions); 1843 console.info('data authResults:' + data.authResults); 1844 }).catch((error: BusinessError) => { 1845 console.error(`Failed to request permissions from user. Code is ${error.code}, message is ${error.message}`); 1846 }) 1847 } 1848 1849 build() { 1850 Column() { 1851 Web({ src: $rawfile('index.html'), controller: this.controller }) 1852 .onPermissionRequest((event) => { 1853 if (event) { 1854 this.uiContext.showAlertDialog({ 1855 title: 'title', 1856 message: 'text', 1857 primaryButton: { 1858 value: 'deny', 1859 action: () => { 1860 event.request.deny(); 1861 } 1862 }, 1863 secondaryButton: { 1864 value: 'onConfirm', 1865 action: () => { 1866 event.request.grant(event.request.getAccessibleResource()); 1867 } 1868 }, 1869 cancel: () => { 1870 event.request.deny(); 1871 } 1872 }) 1873 } 1874 }) 1875 } 1876 } 1877 } 1878 ``` 1879 1880 加载的html文件。 1881 ```html 1882 <!-- index.html --> 1883 <!DOCTYPE html> 1884 <html> 1885 <head> 1886 <meta charset="UTF-8"> 1887 </head> 1888 <body> 1889 <video id="video" width="500px" height="500px" autoplay></video> 1890 <canvas id="canvas" width="500px" height="500px"></canvas> 1891 <br> 1892 <input type="button" title="HTML5摄像头" value="开启摄像头" onclick="getMedia()"/> 1893 <script> 1894 function getMedia() 1895 { 1896 let constraints = { 1897 video: {width: 500, height: 500}, 1898 audio: true 1899 }; 1900 // 获取video摄像头区域 1901 let video = document.getElementById("video"); 1902 // 返回的Promise对象 1903 let promise = navigator.mediaDevices.getUserMedia(constraints); 1904 // then()异步,调用MediaStream对象作为参数 1905 promise.then(function (MediaStream) { 1906 video.srcObject = MediaStream; 1907 video.play(); 1908 }).catch(function(error) { 1909 console.error("Error accessing media devices.", error); 1910 }); 1911 } 1912 </script> 1913 </body> 1914 </html> 1915 ``` 1916 1917## onContextMenuShow<sup>9+</sup> 1918 1919onContextMenuShow(callback: Callback\<OnContextMenuShowEvent, boolean\>) 1920 1921长按特定元素(例如图片,链接)或鼠标右键,跳出菜单。 1922 1923**系统能力:** SystemCapability.Web.Webview.Core 1924 1925**参数:** 1926 1927| 参数名 | 类型 | 必填 | 说明 | 1928| ------ | ------ | ---- | --------------------- | 1929| callback | Callback\<[OnContextMenuShowEvent](./arkts-basic-components-web-i.md#oncontextmenushowevent12), boolean\> | 是 | 调用时触发的回调,以允许自定义显示上下文菜单。<br>返回值boolean。返回true表示触发自定义菜单,返回false表示触发的自定义菜单无效。 | 1930 1931**示例:** 1932 1933 ```ts 1934 // xxx.ets 1935 import { webview } from '@kit.ArkWeb'; 1936 import { pasteboard } from '@kit.BasicServicesKit'; 1937 1938 const TAG = 'ContextMenu'; 1939 1940 @Entry 1941 @Component 1942 struct WebComponent { 1943 controller: webview.WebviewController = new webview.WebviewController(); 1944 private result: WebContextMenuResult | undefined = undefined; 1945 @State linkUrl: string = ''; 1946 @State offsetX: number = 0; 1947 @State offsetY: number = 0; 1948 @State showMenu: boolean = false; 1949 uiContext: UIContext = this.getUIContext(); 1950 1951 @Builder 1952 // 构建自定义菜单及触发功能接口 1953 MenuBuilder() { 1954 // 以垂直列表形式显示的菜单。 1955 Menu() { 1956 // 展示菜单Menu中具体的item菜单项。 1957 MenuItem({ 1958 content: '撤销', 1959 }) 1960 .width(100) 1961 .height(50) 1962 .onClick(() => { 1963 this.result?.undo(); 1964 this.showMenu = false; 1965 }) 1966 MenuItem({ 1967 content: '重做', 1968 }) 1969 .width(100) 1970 .height(50) 1971 .onClick(() => { 1972 this.result?.redo(); 1973 this.showMenu = false; 1974 }) 1975 MenuItem({ 1976 content: '粘贴为纯文本', 1977 }) 1978 .width(100) 1979 .height(50) 1980 .onClick(() => { 1981 this.result?.pasteAndMatchStyle(); 1982 this.showMenu = false; 1983 }) 1984 MenuItem({ 1985 content: '复制图片', 1986 }) 1987 .width(100) 1988 .height(50) 1989 .onClick(() => { 1990 this.result?.copyImage(); 1991 this.showMenu = false; 1992 }) 1993 MenuItem({ 1994 content: '剪切', 1995 }) 1996 .width(100) 1997 .height(50) 1998 .onClick(() => { 1999 this.result?.cut(); 2000 this.showMenu = false; 2001 }) 2002 MenuItem({ 2003 content: '复制', 2004 }) 2005 .width(100) 2006 .height(50) 2007 .onClick(() => { 2008 this.result?.copy(); 2009 this.showMenu = false; 2010 }) 2011 MenuItem({ 2012 content: '粘贴', 2013 }) 2014 .width(100) 2015 .height(50) 2016 .onClick(() => { 2017 this.result?.paste(); 2018 this.showMenu = false; 2019 }) 2020 MenuItem({ 2021 content: '复制链接', 2022 }) 2023 .width(100) 2024 .height(50) 2025 .onClick(() => { 2026 let pasteData = pasteboard.createData('text/plain', this.linkUrl); 2027 pasteboard.getSystemPasteboard().setData(pasteData, (error) => { 2028 if (error) { 2029 return; 2030 } 2031 }) 2032 this.showMenu = false; 2033 }) 2034 MenuItem({ 2035 content: '全选', 2036 }) 2037 .width(100) 2038 .height(50) 2039 .onClick(() => { 2040 this.result?.selectAll(); 2041 this.showMenu = false; 2042 }) 2043 } 2044 .width(150) 2045 .height(450) 2046 } 2047 2048 build() { 2049 Column() { 2050 Web({ src: $rawfile("index.html"), controller: this.controller }) 2051 // 触发自定义弹窗 2052 .onContextMenuShow((event) => { 2053 if (event) { 2054 this.result = event.result 2055 console.info(TAG + "x coord = " + event.param.x()); 2056 console.info(TAG + "link url = " + event.param.getLinkUrl()); 2057 this.linkUrl = event.param.getLinkUrl(); 2058 } 2059 console.info(TAG, `x: ${this.offsetX}, y: ${this.offsetY}`); 2060 this.showMenu = true; 2061 this.offsetX = 0; 2062 this.offsetY = Math.max(this.uiContext!.px2vp(event?.param.y() ?? 0) - 0, 0); 2063 return true; 2064 }) 2065 .bindPopup(this.showMenu, 2066 { 2067 builder: this.MenuBuilder(), 2068 enableArrow: false, 2069 placement: Placement.LeftTop, 2070 offset: { x: this.offsetX, y: this.offsetY }, 2071 mask: false, 2072 onStateChange: (e) => { 2073 if (!e.isVisible) { 2074 this.showMenu = false; 2075 this.result!.closeContextMenu(); 2076 } 2077 } 2078 }) 2079 } 2080 } 2081 } 2082 ``` 2083 2084 加载的html文件。 2085 ```html 2086 <!-- index.html --> 2087 <!DOCTYPE html> 2088 <html lang="en"> 2089 <body> 2090 <h1>onContextMenuShow</h1> 2091 <a href="http://www.example.com" style="font-size:27px">链接www.example.com</a> 2092 <!-- rawfile下放任意一张图片命名为example.png --> 2093 <div><img src="example.png"></div> 2094 <p>选中文字鼠标右键弹出菜单</p> 2095 </body> 2096 </html> 2097 ``` 2098 2099## onContextMenuHide<sup>11+</sup> 2100 2101onContextMenuHide(callback: OnContextMenuHideCallback) 2102 2103长按特定元素(例如图片,链接)或鼠标右键,隐藏菜单。 2104 2105**系统能力:** SystemCapability.Web.Webview.Core 2106 2107**参数:** 2108 2109| 参数名 | 类型 | 必填 | 说明 | 2110| ------ | ------ | ---- | --------------------- | 2111| callback | [OnContextMenuHideCallback](./arkts-basic-components-web-t.md#oncontextmenuhidecallback11) | 是 | 菜单相关回调。 | 2112 2113**示例:** 2114 2115 ```ts 2116 // xxx.ets 2117 import { webview } from '@kit.ArkWeb'; 2118 2119 @Entry 2120 @Component 2121 struct WebComponent { 2122 controller: webview.WebviewController = new webview.WebviewController(); 2123 2124 build() { 2125 Column() { 2126 Web({ src: 'www.example.com', controller: this.controller }) 2127 .onContextMenuHide(() => { 2128 console.info("onContextMenuHide callback"); 2129 }) 2130 } 2131 } 2132 } 2133 ``` 2134 2135## onScroll<sup>9+</sup> 2136 2137onScroll(callback: Callback\<OnScrollEvent\>) 2138 2139通知网页全局滚动位置。 2140 2141> **说明:** 2142> 2143> 通知的是页面全局滚动位置,局部滚动位置的变化是无法触发此回调。 2144> 2145> 判断页面是否是全局滚动,在滚动前后打印window.pagYOffset或者window.pagXOffset。 2146> 2147> 如果是全局滚动,window.pagYOffset或者window.pagXOffset的值在滚动前后会有变化,反之没有变化。 2148 2149**系统能力:** SystemCapability.Web.Webview.Core 2150 2151**参数:** 2152 2153| 参数名 | 类型 | 必填 | 说明 | 2154| ------ | ------ | ---- | --------------------- | 2155| callback | Callback\<[OnScrollEvent](./arkts-basic-components-web-i.md#onscrollevent12)\> | 是 | 当页面滑动到指定位置时触发。 | 2156 2157**示例:** 2158 2159 ```ts 2160 // xxx.ets 2161 import { webview } from '@kit.ArkWeb'; 2162 2163 @Entry 2164 @Component 2165 struct WebComponent { 2166 controller: webview.WebviewController = new webview.WebviewController(); 2167 2168 build() { 2169 Column() { 2170 Web({ src: 'www.example.com', controller: this.controller }) 2171 .onScroll((event) => { 2172 console.info("x = " + event.xOffset); 2173 console.info("y = " + event.yOffset); 2174 }) 2175 } 2176 } 2177 } 2178 ``` 2179 2180## onGeolocationShow 2181 2182onGeolocationShow(callback: Callback\<OnGeolocationShowEvent\>) 2183 2184通知用户收到地理位置信息获取请求,需配置"ohos.permission.LOCATION"、"ohos.permission.APPROXIMATELY_LOCATION"权限。 2185 2186**系统能力:** SystemCapability.Web.Webview.Core 2187 2188**参数:** 2189 2190| 参数名 | 类型 | 必填 | 说明 | 2191| ------ | ------ | ---- | --------------------- | 2192| callback | Callback\<[OnGeolocationShowEvent](./arkts-basic-components-web-i.md#ongeolocationshowevent12)\> | 是 | 请求显示地理位置权限时触发。 | 2193 2194**示例:** 2195 2196 ```ts 2197 // xxx.ets 2198 import { webview } from '@kit.ArkWeb'; 2199 import { BusinessError } from '@kit.BasicServicesKit'; 2200 import { abilityAccessCtrl, common } from '@kit.AbilityKit'; 2201 2202 let atManager = abilityAccessCtrl.createAtManager(); 2203 2204 @Entry 2205 @Component 2206 struct WebComponent { 2207 controller: webview.WebviewController = new webview.WebviewController(); 2208 uiContext: UIContext = this.getUIContext(); 2209 2210 // 组件的声明周期函数,创建组件实例后触发 2211 aboutToAppear(): void { 2212 let context : Context | undefined = this.uiContext.getHostContext() as common.UIAbilityContext; 2213 if (!context) { 2214 console.error("context is undefined"); 2215 return; 2216 } 2217 // 向用户请求位置权限 2218 atManager.requestPermissionsFromUser(context, ["ohos.permission.LOCATION", "ohos.permission.APPROXIMATELY_LOCATION"]).then((data) => { 2219 console.info('data:' + JSON.stringify(data)); 2220 console.info('data permissions:' + data.permissions); 2221 console.info('data authResults:' + data.authResults); 2222 }).catch((error: BusinessError) => { 2223 console.error(`Failed to request permissions from user. Code is ${error.code}, message is ${error.message}`); 2224 }) 2225 } 2226 2227 build() { 2228 Column() { 2229 Web({ src: $rawfile('index.html'), controller: this.controller }) 2230 .geolocationAccess(true) 2231 .onGeolocationShow((event) => { 2232 if (event) { 2233 this.uiContext.showAlertDialog({ 2234 title: 'title', 2235 message: 'text', 2236 confirm: { 2237 value: 'onConfirm', 2238 action: () => { 2239 // invoke的第三个参数表示是否记住当前弹窗的选择状态,如果传入true,则下次不再弹出对话框 2240 event.geolocation.invoke(event.origin, true, false); 2241 } 2242 }, 2243 cancel: () => { 2244 // invoke的第三个参数表示是否记住当前弹窗的选择状态,如果传入true,则下次不再弹出对话框 2245 event.geolocation.invoke(event.origin, false, false); 2246 } 2247 }) 2248 } 2249 }) 2250 } 2251 } 2252 } 2253 ``` 2254 2255 加载的html文件。 2256 ```html 2257 <!DOCTYPE html> 2258 <html> 2259 <body> 2260 <p id="locationInfo">位置信息</p> 2261 <button onclick="getLocation()">获取位置</button> 2262 <script> 2263 var locationInfo=document.getElementById("locationInfo"); 2264 function getLocation(){ 2265 if (navigator.geolocation) { 2266 // 前端页面访问设备地理位置 2267 navigator.geolocation.getCurrentPosition(showPosition); 2268 } 2269 } 2270 function showPosition(position){ 2271 locationInfo.innerHTML="Latitude: " + position.coords.latitude + "<br />Longitude: " + position.coords.longitude; 2272 } 2273 </script> 2274 </body> 2275 </html> 2276 ``` 2277 2278## onGeolocationHide 2279 2280onGeolocationHide(callback: () => void) 2281 2282通知用户先前被调用[onGeolocationShow](#ongeolocationshow)时收到地理位置信息获取请求已被取消。 2283 2284**系统能力:** SystemCapability.Web.Webview.Core 2285 2286**参数:** 2287 2288| 参数名 | 类型 | 必填 | 说明 | 2289| ------ | ------ | ---- | --------------------- | 2290| callback | () => void | 是 | 地理位置信息获取请求已被取消的回调函数。 | 2291 2292**示例:** 2293 2294 ```ts 2295 // xxx.ets 2296 import { webview } from '@kit.ArkWeb'; 2297 2298 @Entry 2299 @Component 2300 struct WebComponent { 2301 controller: webview.WebviewController = new webview.WebviewController(); 2302 2303 build() { 2304 Column() { 2305 Web({ src: 'www.example.com', controller: this.controller }) 2306 .geolocationAccess(true) 2307 .onGeolocationHide(() => { 2308 console.info("onGeolocationHide..."); 2309 }) 2310 } 2311 } 2312 } 2313 ``` 2314 2315## onFullScreenEnter<sup>9+</sup> 2316 2317onFullScreenEnter(callback: OnFullScreenEnterCallback) 2318 2319通知开发者Web组件进入全屏模式。 2320 2321**系统能力:** SystemCapability.Web.Webview.Core 2322 2323**参数:** 2324 2325| 参数名 | 类型 | 必填 | 说明 | 2326| ------ | ------ | ---- | --------------------- | 2327| callback | [OnFullScreenEnterCallback](./arkts-basic-components-web-t.md#onfullscreenentercallback12) | 是 | Web组件进入全屏时的回调信息。 | 2328 2329**示例:** 2330 2331 ```ts 2332 // xxx.ets 2333 import { webview } from '@kit.ArkWeb'; 2334 2335 @Entry 2336 @Component 2337 struct WebComponent { 2338 controller: webview.WebviewController = new webview.WebviewController(); 2339 handler: FullScreenExitHandler | null = null; 2340 2341 build() { 2342 Column() { 2343 Web({ src: 'www.example.com', controller: this.controller }) 2344 .onFullScreenEnter((event) => { 2345 console.info("onFullScreenEnter videoWidth: " + event.videoWidth + 2346 ", videoHeight: " + event.videoHeight); 2347 // 应用可以通过 this.handler.exitFullScreen() 主动退出全屏。 2348 this.handler = event.handler; 2349 }) 2350 } 2351 } 2352 } 2353 ``` 2354 2355## onFullScreenExit<sup>9+</sup> 2356 2357onFullScreenExit(callback: () => void) 2358 2359通知开发者Web组件退出全屏模式。 2360 2361**系统能力:** SystemCapability.Web.Webview.Core 2362 2363**参数:** 2364 2365| 参数名 | 类型 | 必填 | 说明 | 2366| ------ | ------ | ---- | --------------------- | 2367| callback | () => void | 是 | 退出全屏模式时的回调函数。 | 2368 2369**示例:** 2370 2371 ```ts 2372 // xxx.ets 2373 import { webview } from '@kit.ArkWeb'; 2374 2375 @Entry 2376 @Component 2377 struct WebComponent { 2378 controller: webview.WebviewController = new webview.WebviewController(); 2379 handler: FullScreenExitHandler | null = null; 2380 2381 build() { 2382 Column() { 2383 Web({ src: 'www.example.com', controller: this.controller }) 2384 .onFullScreenExit(() => { 2385 console.info("onFullScreenExit...") 2386 if (this.handler) { 2387 this.handler.exitFullScreen(); 2388 } 2389 }) 2390 .onFullScreenEnter((event) => { 2391 this.handler = event.handler; 2392 }) 2393 } 2394 } 2395 } 2396 ``` 2397 2398## onWindowNew<sup>9+</sup> 2399 2400onWindowNew(callback: Callback\<OnWindowNewEvent\>) 2401 2402使能multiWindowAccess情况下,通知用户新建窗口请求。 2403若不调用[setWebController](./arkts-basic-components-web-ControllerHandler.md#setwebcontroller9)接口,会造成render进程阻塞。 2404如果没有创建新窗口,调用[setWebController](./arkts-basic-components-web-ControllerHandler.md#setwebcontroller9)接口时设置成null,通知Web没有创建新窗口。 2405 2406新窗口需避免直接覆盖在原Web组件上,且应与主页面以相同形式明确显示其URL(如地址栏)以防止用户混淆。若无法实现可信的URL可视化管理,则需考虑禁止创建新窗口。 2407需注意:新窗口请求来源无法可靠追溯,可能由第三方iframe发起,应用需默认采取沙箱隔离、限制权限等防御性措施以确保安全。 2408 2409**系统能力:** SystemCapability.Web.Webview.Core 2410 2411**参数:** 2412 2413| 参数名 | 类型 | 必填 | 说明 | 2414| ------ | ------ | ---- | --------------------- | 2415| callback | Callback\<[OnWindowNewEvent](./arkts-basic-components-web-i.md#onwindownewevent12)\> | 是 | 网页要求用户创建窗口时触发的回调。 | 2416 2417**示例:** 2418 2419 ```ts 2420 // xxx.ets 2421 import { webview } from '@kit.ArkWeb'; 2422 2423 // 在同一page页有两个Web组件。在WebComponent新开窗口时,会跳转到NewWebViewComp。 2424 @CustomDialog 2425 struct NewWebViewComp { 2426 controller?: CustomDialogController; 2427 webviewController1: webview.WebviewController = new webview.WebviewController(); 2428 2429 build() { 2430 Column() { 2431 Web({ src: "www.example.com", controller: this.webviewController1 }) 2432 .javaScriptAccess(true) 2433 .multiWindowAccess(false) 2434 .onWindowExit(() => { 2435 console.info("NewWebViewComp onWindowExit"); 2436 if (this.controller) { 2437 this.controller.close(); 2438 } 2439 }) 2440 } 2441 } 2442 } 2443 2444 @Entry 2445 @Component 2446 struct WebComponent { 2447 controller: webview.WebviewController = new webview.WebviewController(); 2448 dialogController: CustomDialogController | null = null; 2449 2450 build() { 2451 Column() { 2452 Web({ src: $rawfile("window.html"), controller: this.controller }) 2453 .javaScriptAccess(true) 2454 // 需要使能multiWindowAccess 2455 .multiWindowAccess(true) 2456 .allowWindowOpenMethod(true) 2457 .onWindowNew((event) => { 2458 if (this.dialogController) { 2459 this.dialogController.close(); 2460 } 2461 let popController: webview.WebviewController = new webview.WebviewController(); 2462 this.dialogController = new CustomDialogController({ 2463 builder: NewWebViewComp({ webviewController1: popController }) 2464 }) 2465 this.dialogController.open(); 2466 // 将新窗口对应WebviewController返回给Web内核。 2467 // 若不调用event.handler.setWebController接口,会造成render进程阻塞。 2468 // 如果没有创建新窗口,调用event.handler.setWebController接口时设置成null,通知Web没有创建新窗口。 2469 event.handler.setWebController(popController); 2470 }) 2471 } 2472 } 2473 } 2474 ``` 2475 2476 ```html 2477 <!-- window.html页面代码 --> 2478 <!DOCTYPE html> 2479 <html> 2480 <head> 2481 <meta charset="UTF-8"> 2482 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 2483 </head> 2484 <body> 2485 <a href="#" onclick="openNewWindow('https://www.example.com')">打开新页面</a> 2486 <script type="text/javascript"> 2487 function openNewWindow(url) { 2488 window.open(url, 'example'); 2489 return false; 2490 } 2491 </script> 2492 </body> 2493 </html> 2494 ``` 2495 2496## onActivateContent<sup>20+</sup> 2497 2498onActivateContent(callback: Callback\<void>) 2499 2500当Web页面触发window.open(url, name)时,会根据name查找是否存在已绑定的Web实例。若存在,该实例将收到此回调以通知应用需将其展示至前端;若不存在,则通过[onWindowNew](#onwindownew9)通知应用创建新Web实例。 2501 2502> **说明:** 2503> 2504> - 通过name绑定Web实例:需在[onWindowNew](#onwindownew9)回调中调用event.handler.setWebController方法,并传入新Web实例的controller,以完成绑定。 2505> - name命名需符合正则表达式[a-zA-Z0-9_]+。当该name被用作\<a>或\<form>标签的target属性值时,已绑定的Web实例同样会触发此回调。 2506 2507**系统能力:** SystemCapability.Web.Webview.Core 2508 2509**参数** 2510 2511| 参数名 | 类型 | 必填 | 说明 | 2512| ------------- | ---------------- | ---- | --------------------------------- | 2513| callback | Callback\<void> | 是 | 再次在原页面触发window.open后,在已打开的新页面触发该回调。 | 2514 2515**示例:** 2516 2517 ```ts 2518 // xxx.ets 2519 import { webview } from '@kit.ArkWeb'; 2520 2521 // 在同一page页有两个Web组件。在WebComponent新开窗口时,会跳转到NewWebViewComp。 2522 @CustomDialog 2523 struct NewWebViewComp { 2524 controller?: CustomDialogController; 2525 webviewController1: webview.WebviewController = new webview.WebviewController(); 2526 2527 build() { 2528 Column() { 2529 Web({ src: "https://www.example.com", controller: this.webviewController1 }) 2530 .javaScriptAccess(true) 2531 .multiWindowAccess(false) 2532 .onWindowExit(() => { 2533 if (this.controller) { 2534 this.controller.close(); 2535 } 2536 }) 2537 .onActivateContent(() => { 2538 //该Web需要展示到前面,建议应用在这里进行tab或window切换的动作展示此web 2539 console.info("NewWebViewComp onActivateContent") 2540 }) 2541 }.height("50%") 2542 } 2543 } 2544 2545 @Entry 2546 @Component 2547 struct WebComponent { 2548 controller: webview.WebviewController = new webview.WebviewController(); 2549 dialogController: CustomDialogController | null = null; 2550 2551 build() { 2552 Column() { 2553 Web({ src: $rawfile("window.html"), controller: this.controller }) 2554 .javaScriptAccess(true) 2555 .allowWindowOpenMethod(true) 2556 // 需要使能multiWindowAccess 2557 .multiWindowAccess(true) 2558 .onWindowNew((event) => { 2559 if (this.dialogController) { 2560 this.dialogController.close() 2561 } 2562 let popController: webview.WebviewController = new webview.WebviewController(); 2563 this.dialogController = new CustomDialogController({ 2564 builder: NewWebViewComp({ webviewController1: popController }), 2565 isModal: false 2566 }) 2567 this.dialogController.open(); 2568 // 将新窗口对应WebviewController返回给Web内核。 2569 // 若不调用event.handler.setWebController接口,会造成render进程阻塞。 2570 event.handler.setWebController(popController); 2571 }) 2572 } 2573 } 2574 } 2575 ``` 2576 2577 ```html 2578 <!-- window.html页面代码 --> 2579 <!DOCTYPE html> 2580 <html> 2581 <head> 2582 <meta charset="UTF-8"> 2583 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 2584 <title>ActivateContentEvent</title> 2585 </head> 2586 <body> 2587 <a href="#" onclick="openNewWindow('https://www.example.com')">打开新页面</a> 2588 <script type="text/javascript"> 2589 function openNewWindow(url) { 2590 window.open(url, 'example'); 2591 return false; 2592 } 2593 </script> 2594 </body> 2595 </html> 2596 ``` 2597 2598## onWindowExit<sup>9+</sup> 2599 2600onWindowExit(callback: () => void) 2601 2602通知用户窗口关闭请求。和[onWindowNew](#onwindownew9)一样,从安全角度讲,应用应该确保用户可以知道他们交互的页面已关闭。 2603 2604**系统能力:** SystemCapability.Web.Webview.Core 2605 2606**参数:** 2607 2608| 参数名 | 类型 | 必填 | 说明 | 2609| ------ | ------ | ---- | --------------------- | 2610| callback | () => void | 是 | 窗口请求关闭的回调函数。 | 2611 2612**示例:** 2613 2614 ```ts 2615 // xxx.ets 2616 import { webview } from '@kit.ArkWeb'; 2617 2618 @Entry 2619 @Component 2620 struct WebComponent { 2621 controller: webview.WebviewController = new webview.WebviewController(); 2622 2623 build() { 2624 Column() { 2625 Web({ src: 'www.example.com', controller: this.controller }) 2626 .onWindowExit(() => { 2627 console.info("onWindowExit..."); 2628 }) 2629 } 2630 } 2631 } 2632 ``` 2633 2634## onSearchResultReceive<sup>9+</sup> 2635 2636onSearchResultReceive(callback: Callback\<OnSearchResultReceiveEvent\>) 2637 2638回调通知调用方网页页内查找的结果。 2639 2640**系统能力:** SystemCapability.Web.Webview.Core 2641 2642**参数:** 2643 2644| 参数名 | 类型 | 必填 | 说明 | 2645| ------ | ------ | ---- | --------------------- | 2646| callback | Callback\<[OnSearchResultReceiveEvent](./arkts-basic-components-web-i.md#onsearchresultreceiveevent12)\> | 是 | 通知调用方网页页内查找的结果。 | 2647 2648**示例:** 2649 2650 ```ts 2651 // xxx.ets 2652 import { webview } from '@kit.ArkWeb'; 2653 2654 @Entry 2655 @Component 2656 struct WebComponent { 2657 controller: webview.WebviewController = new webview.WebviewController(); 2658 2659 build() { 2660 Column() { 2661 Web({ src: 'www.example.com', controller: this.controller }) 2662 .onSearchResultReceive(ret => { 2663 if (ret) { 2664 console.info("on search result receive:" + "[cur]" + ret.activeMatchOrdinal + 2665 "[total]" + ret.numberOfMatches + "[isDone]" + ret.isDoneCounting); 2666 } 2667 }) 2668 } 2669 } 2670 } 2671 ``` 2672 2673## onDataResubmitted<sup>9+</sup> 2674 2675onDataResubmitted(callback: Callback\<OnDataResubmittedEvent\>) 2676 2677设置网页表单可以重新提交时触发的回调函数。 2678 2679**系统能力:** SystemCapability.Web.Webview.Core 2680 2681**参数:** 2682 2683| 参数名 | 类型 | 必填 | 说明 | 2684| ------ | ------ | ---- | --------------------- | 2685| callback | Callback\<[OnDataResubmittedEvent](./arkts-basic-components-web-i.md#ondataresubmittedevent12)\> | 是 | 网页表单可以重新提交时触发。 | 2686 2687**示例:** 2688 2689 ```ts 2690 // xxx.ets 2691 import { webview } from '@kit.ArkWeb'; 2692 import { BusinessError } from '@kit.BasicServicesKit'; 2693 2694 @Entry 2695 @Component 2696 struct WebComponent { 2697 controller: webview.WebviewController = new webview.WebviewController(); 2698 2699 build() { 2700 Column() { 2701 // 在网页中点击提交之后,点击refresh按钮可以重新提交时的触发函数。 2702 Button('refresh') 2703 .onClick(() => { 2704 try { 2705 this.controller.refresh(); 2706 } catch (error) { 2707 console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`); 2708 } 2709 }) 2710 Web({ src: $rawfile('index.html'), controller: this.controller }) 2711 .onDataResubmitted((event) => { 2712 console.info('onDataResubmitted'); 2713 event.handler.resend(); 2714 }) 2715 } 2716 } 2717 } 2718 ``` 2719 2720 加载的html文件。 2721 ```html 2722 <!-- index.html --> 2723 <!DOCTYPE html> 2724 <html> 2725 <head> 2726 <meta charset="utf-8"> 2727 </head> 2728 <body> 2729 <form action="http://httpbin.org/post" method="post"> 2730 <input type="text" name="username"> 2731 <input type="submit" name="提交"> 2732 </form> 2733 </body> 2734 </html> 2735 ``` 2736 2737## onPageVisible<sup>9+</sup> 2738 2739onPageVisible(callback: Callback\<OnPageVisibleEvent\>) 2740 2741设置旧页面不再呈现,新页面即将可见时触发的回调函数。 2742 2743**系统能力:** SystemCapability.Web.Webview.Core 2744 2745**参数:** 2746 2747| 参数名 | 类型 | 必填 | 说明 | 2748| ------ | ------ | ---- | --------------------- | 2749| callback | Callback\<[OnPageVisibleEvent](./arkts-basic-components-web-i.md#onpagevisibleevent12)\> | 是 | 旧页面不再呈现,新页面即将可见时触发的回调函数。 | 2750 2751**示例:** 2752 2753 ```ts 2754 // xxx.ets 2755 import { webview } from '@kit.ArkWeb'; 2756 2757 @Entry 2758 @Component 2759 struct WebComponent { 2760 controller: webview.WebviewController = new webview.WebviewController(); 2761 2762 build() { 2763 Column() { 2764 Web({ src: 'www.example.com', controller: this.controller }) 2765 .onPageVisible((event) => { 2766 console.info('onPageVisible url:' + event.url); 2767 }) 2768 } 2769 } 2770 } 2771 ``` 2772 2773## onInterceptKeyEvent<sup>9+</sup> 2774 2775onInterceptKeyEvent(callback: (event: KeyEvent) => boolean) 2776 2777设置键盘事件的回调函数,该回调在被Webview使用前触发。 2778 2779**系统能力:** SystemCapability.Web.Webview.Core 2780 2781**参数:** 2782 2783| 参数名 | 类型 | 必填 | 说明 | 2784| ------ | ------ | ---- | --------------------- | 2785| callback | (event:[KeyEvent](../apis-arkui/arkui-ts/ts-universal-events-key.md#keyevent对象说明)) => boolean | 是 | 触发的KeyEvent事件。<br>返回值为boolean类型,true表示将该KeyEvent传入Webview内核,false表示不将该KeyEvent传入ArkWeb内核。 | 2786 2787**示例:** 2788 2789 ```ts 2790 // xxx.ets 2791 import { webview } from '@kit.ArkWeb'; 2792 2793 @Entry 2794 @Component 2795 struct WebComponent { 2796 controller: webview.WebviewController = new webview.WebviewController(); 2797 2798 build() { 2799 Column() { 2800 Web({ src: 'www.example.com', controller: this.controller }) 2801 .onInterceptKeyEvent((event) => { 2802 if (event.keyCode == 2017 || event.keyCode == 2018) { 2803 console.info(`onInterceptKeyEvent get event.keyCode ${event.keyCode}`); 2804 return true; 2805 } 2806 return false; 2807 }) 2808 } 2809 } 2810 } 2811 ``` 2812 2813## onTouchIconUrlReceived<sup>9+</sup> 2814 2815onTouchIconUrlReceived(callback: Callback\<OnTouchIconUrlReceivedEvent\>) 2816 2817设置接收到apple-touch-icon url地址时的回调函数。 2818 2819**系统能力:** SystemCapability.Web.Webview.Core 2820 2821**参数:** 2822 2823| 参数名 | 类型 | 必填 | 说明 | 2824| ------ | ------ | ---- | --------------------- | 2825| callback | Callback\<[OnTouchIconUrlReceivedEvent](./arkts-basic-components-web-i.md#ontouchiconurlreceivedevent12)\> | 是 | 接收到的apple-touch-icon url地址时触发。 | 2826 2827**示例:** 2828 2829 ```ts 2830 // xxx.ets 2831 import { webview } from '@kit.ArkWeb'; 2832 2833 @Entry 2834 @Component 2835 struct WebComponent { 2836 controller: webview.WebviewController = new webview.WebviewController(); 2837 2838 build() { 2839 Column() { 2840 Web({ src: 'www.baidu.com', controller: this.controller }) 2841 .onTouchIconUrlReceived((event) => { 2842 console.info('onTouchIconUrlReceived:' + JSON.stringify(event)); 2843 }) 2844 } 2845 } 2846 } 2847 ``` 2848 2849## onFaviconReceived<sup>9+</sup> 2850 2851onFaviconReceived(callback: Callback\<OnFaviconReceivedEvent\>) 2852 2853设置应用为当前页面接收到新的favicon时的回调函数。 2854 2855**系统能力:** SystemCapability.Web.Webview.Core 2856 2857**参数:** 2858 2859| 参数名 | 类型 | 必填 | 说明 | 2860| ------ | ------ | ---- | --------------------- | 2861| callback | Callback\<[OnFaviconReceivedEvent](./arkts-basic-components-web-i.md#onfaviconreceivedevent12)\> | 是 | 当前页面接收到新的favicon时触发。 | 2862 2863**示例:** 2864 2865 ```ts 2866 // xxx.ets 2867 import { webview } from '@kit.ArkWeb'; 2868 import { image } from '@kit.ImageKit'; 2869 2870 @Entry 2871 @Component 2872 struct WebComponent { 2873 controller: webview.WebviewController = new webview.WebviewController(); 2874 @State icon: image.PixelMap | undefined = undefined; 2875 2876 build() { 2877 Column() { 2878 Web({ src: 'www.example.com', controller: this.controller }) 2879 .onFaviconReceived((event) => { 2880 console.info('onFaviconReceived'); 2881 this.icon = event.favicon; 2882 }) 2883 } 2884 } 2885 } 2886 ``` 2887 2888## onAudioStateChanged<sup>10+</sup> 2889 2890onAudioStateChanged(callback: Callback\<OnAudioStateChangedEvent\>) 2891 2892设置网页上的音频播放状态发生改变时的回调函数。 2893 2894**系统能力:** SystemCapability.Web.Webview.Core 2895 2896**参数:** 2897 2898| 参数名 | 类型 | 必填 | 说明 | 2899| ------ | ------ | ---- | --------------------- | 2900| callback | Callback\<[OnAudioStateChangedEvent](./arkts-basic-components-web-i.md#onaudiostatechangedevent12)\> | 是 | 网页上的音频播放状态发生改变时触发。 | 2901 2902**示例:** 2903 2904 ```ts 2905 // xxx.ets 2906 import { webview } from '@kit.ArkWeb'; 2907 2908 @Entry 2909 @Component 2910 struct WebComponent { 2911 controller: webview.WebviewController = new webview.WebviewController(); 2912 @State playing: boolean = false; 2913 2914 build() { 2915 Column() { 2916 Web({ src: 'www.example.com', controller: this.controller }) 2917 .onAudioStateChanged(event => { 2918 this.playing = event.playing; 2919 console.info('onAudioStateChanged playing: ' + this.playing); 2920 }) 2921 } 2922 } 2923 } 2924 ``` 2925 2926## onFirstContentfulPaint<sup>10+</sup> 2927 2928 onFirstContentfulPaint(callback: Callback\<OnFirstContentfulPaintEvent\>) 2929 2930设置网页首次内容绘制回调函数。 2931 2932**系统能力:** SystemCapability.Web.Webview.Core 2933 2934**参数:** 2935 2936| 参数名 | 类型 | 必填 | 说明 | 2937| ------ | ------ | ---- | --------------------- | 2938| callback | Callback\<[OnFirstContentfulPaintEvent](./arkts-basic-components-web-i.md#onfirstcontentfulpaintevent12)\> | 是 | 网页首次内容绘制回调函数。 | 2939 2940**示例:** 2941 2942 ```ts 2943 // xxx.ets 2944 import { webview } from '@kit.ArkWeb'; 2945 2946 @Entry 2947 @Component 2948 struct WebComponent { 2949 controller: webview.WebviewController = new webview.WebviewController(); 2950 2951 build() { 2952 Column() { 2953 Web({ src: 'www.example.com', controller: this.controller }) 2954 .onFirstContentfulPaint(event => { 2955 if (event) { 2956 console.info("onFirstContentfulPaint:" + "[navigationStartTick]:" + 2957 event.navigationStartTick + ", [firstContentfulPaintMs]:" + 2958 event.firstContentfulPaintMs); 2959 } 2960 }) 2961 } 2962 } 2963 } 2964 ``` 2965 2966## onFirstMeaningfulPaint<sup>12+</sup> 2967 2968onFirstMeaningfulPaint(callback: [OnFirstMeaningfulPaintCallback](./arkts-basic-components-web-t.md#onfirstmeaningfulpaintcallback12)) 2969 2970设置网页绘制页面主要内容回调函数。 2971 2972**系统能力:** SystemCapability.Web.Webview.Core 2973 2974**参数:** 2975 2976| 参数名 | 类型 | 必填 | 说明 | 2977| ------ | ------ | ---- | --------------------- | 2978| callback | [OnFirstMeaningfulPaintCallback](./arkts-basic-components-web-t.md#onfirstmeaningfulpaintcallback12) | 是 | 网页绘制页面主要内容度量信息的回调。 | 2979 2980**示例:** 2981 2982 ```ts 2983 // xxx.ets 2984 import { webview } from '@kit.ArkWeb'; 2985 2986 @Entry 2987 @Component 2988 struct WebComponent { 2989 controller: webview.WebviewController = new webview.WebviewController(); 2990 2991 build() { 2992 Column() { 2993 Web({ src: 'www.example.com', controller: this.controller }) 2994 .onFirstMeaningfulPaint((details) => { 2995 console.log("onFirstMeaningfulPaint: [navigationStartTime]= " + details.navigationStartTime + 2996 ", [firstMeaningfulPaintTime]=" + details.firstMeaningfulPaintTime); 2997 }) 2998 } 2999 } 3000 } 3001 ``` 3002 3003## onLargestContentfulPaint<sup>12+</sup> 3004 3005onLargestContentfulPaint(callback: [OnLargestContentfulPaintCallback](./arkts-basic-components-web-t.md#onlargestcontentfulpaintcallback12)) 3006 3007设置网页绘制页面最大内容回调函数。 3008 3009**系统能力:** SystemCapability.Web.Webview.Core 3010 3011**参数:** 3012 3013| 参数名 | 类型 | 必填 | 说明 | 3014| ------ | ------ | ---- | --------------------- | 3015| callback | [OnLargestContentfulPaintCallback](./arkts-basic-components-web-t.md#onlargestcontentfulpaintcallback12) | 是 | 网页绘制页面最大内容度量信息的回调。 | 3016 3017**示例:** 3018 3019 ```ts 3020 // xxx.ets 3021 import { webview } from '@kit.ArkWeb'; 3022 3023 @Entry 3024 @Component 3025 struct WebComponent { 3026 controller: webview.WebviewController = new webview.WebviewController(); 3027 3028 build() { 3029 Column() { 3030 Web({ src: 'www.example.com', controller: this.controller }) 3031 .onLargestContentfulPaint((details) => { 3032 console.info("onLargestContentfulPaint: [navigationStartTime]= " + details.navigationStartTime + 3033 ", [largestImagePaintTime]=" + details.largestImagePaintTime + 3034 ", [largestTextPaintTime]=" + details.largestTextPaintTime + 3035 ", [largestImageLoadStartTime]=" + details.largestImageLoadStartTime + 3036 ", [largestImageLoadEndTime]=" + details.largestImageLoadEndTime + 3037 ", [imageBPP]=" + details.imageBPP); 3038 }) 3039 } 3040 } 3041 } 3042 ``` 3043 3044## onLoadIntercept<sup>10+</sup> 3045 3046onLoadIntercept(callback: Callback\<OnLoadInterceptEvent, boolean\>) 3047 3048当Web组件加载url之前触发该回调,用于判断是否阻止此次访问。 3049 3050**系统能力:** SystemCapability.Web.Webview.Core 3051 3052**参数:** 3053 3054| 参数名 | 类型 | 必填 | 说明 | 3055| ------ | ------ | ---- | --------------------- | 3056| callback | Callback\<[OnLoadInterceptEvent](./arkts-basic-components-web-i.md#onloadinterceptevent12), boolean\> | 是 | 导航触发时的回调包括iframe导航,在回调中可以选择允许或者取消此次导航。<br>返回值为boolean类型。返回true表示取消此次导航,false表示允许此次导航。<br>返回undefined或null时允许此次导航。 | 3057 3058**示例:** 3059 3060 ```ts 3061 // xxx.ets 3062 import { webview } from '@kit.ArkWeb'; 3063 3064 @Entry 3065 @Component 3066 struct WebComponent { 3067 controller: webview.WebviewController = new webview.WebviewController(); 3068 3069 build() { 3070 Column() { 3071 Web({ src: 'www.example.com', controller: this.controller }) 3072 .onLoadIntercept((event) => { 3073 console.info('url:' + event.data.getRequestUrl()); 3074 console.info('isMainFrame:' + event.data.isMainFrame()); 3075 console.info('isRedirect:' + event.data.isRedirect()); 3076 console.info('isRequestGesture:' + event.data.isRequestGesture()); 3077 return true; 3078 }) 3079 } 3080 } 3081 } 3082 ``` 3083 3084## onRequestSelected 3085 3086onRequestSelected(callback: () => void) 3087 3088当Web组件获取焦点时触发回调。如果组件在未获焦状态下加载网页并成功获取焦点,将触发两次回调。 3089 3090**系统能力:** SystemCapability.Web.Webview.Core 3091 3092**参数:** 3093 3094| 参数名 | 类型 | 必填 | 说明 | 3095| ------ | ------ | ---- | --------------------- | 3096| callback | () => void | 是 | 当网页获取焦点时触发的回调。 | 3097 3098**示例:** 3099 3100 ```ts 3101 // xxx.ets 3102 import { webview } from '@kit.ArkWeb'; 3103 3104 @Entry 3105 @Component 3106 struct WebComponent { 3107 controller: webview.WebviewController = new webview.WebviewController(); 3108 3109 build() { 3110 Column() { 3111 Web({ src: 'www.example.com', controller: this.controller }) 3112 .onRequestSelected(() => { 3113 console.info('onRequestSelected'); 3114 }) 3115 } 3116 } 3117 } 3118 ``` 3119## onScreenCaptureRequest<sup>10+</sup> 3120 3121onScreenCaptureRequest(callback: Callback\<OnScreenCaptureRequestEvent\>) 3122 3123通知收到屏幕捕获请求。 3124 3125**系统能力:** SystemCapability.Web.Webview.Core 3126 3127**参数:** 3128 3129| 参数名 | 类型 | 必填 | 说明 | 3130| ------ | ------ | ---- | --------------------- | 3131| callback | Callback\<[OnScreenCaptureRequestEvent](./arkts-basic-components-web-i.md#onscreencapturerequestevent12)\> | 是 | 通知收到屏幕捕获请求。 | 3132 3133**示例:** 3134 3135 ```ts 3136 // xxx.ets 3137 import { webview } from '@kit.ArkWeb'; 3138 3139 @Entry 3140 @Component 3141 struct WebComponent { 3142 controller: webview.WebviewController = new webview.WebviewController(); 3143 uiContext: UIContext = this.getUIContext(); 3144 3145 build() { 3146 Column() { 3147 Web({ src: 'www.example.com', controller: this.controller }) 3148 .onScreenCaptureRequest((event) => { 3149 if (event) { 3150 this.uiContext.showAlertDialog({ 3151 title: 'title: ' + event.handler.getOrigin(), 3152 message: 'text', 3153 primaryButton: { 3154 value: 'deny', 3155 action: () => { 3156 event.handler.deny(); 3157 } 3158 }, 3159 secondaryButton: { 3160 value: 'onConfirm', 3161 action: () => { 3162 event.handler.grant({ captureMode: WebCaptureMode.HOME_SCREEN }); 3163 } 3164 }, 3165 cancel: () => { 3166 event.handler.deny(); 3167 } 3168 }) 3169 } 3170 }) 3171 } 3172 } 3173 } 3174 ``` 3175 3176## onOverScroll<sup>10+</sup> 3177 3178onOverScroll(callback: Callback\<OnOverScrollEvent\>) 3179 3180该接口在网页过度滚动时触发,用于通知网页过度滚动的偏移量。 3181 3182**系统能力:** SystemCapability.Web.Webview.Core 3183 3184**参数:** 3185 3186| 参数名 | 类型 | 必填 | 说明 | 3187| ------ | ------ | ---- | --------------------- | 3188| callback | Callback\<[OnOverScrollEvent](./arkts-basic-components-web-i.md#onoverscrollevent12)\> | 是 | 网页过度滚动时触发。 | 3189 3190**示例:** 3191 3192 ```ts 3193 // xxx.ets 3194 import { webview } from '@kit.ArkWeb'; 3195 3196 @Entry 3197 @Component 3198 struct WebComponent { 3199 controller: webview.WebviewController = new webview.WebviewController(); 3200 3201 build() { 3202 Column() { 3203 Web({ src: 'www.example.com', controller: this.controller }) 3204 .onOverScroll((event) => { 3205 console.info("x = " + event.xOffset); 3206 console.info("y = " + event.yOffset); 3207 }) 3208 } 3209 } 3210 } 3211 ``` 3212 3213## onControllerAttached<sup>10+</sup> 3214 3215onControllerAttached(callback: () => void) 3216 3217当Controller成功绑定到Web组件时触发该回调,并且该Controller必须为WebviewController,且禁止在该事件回调前调用Web组件相关的接口,否则会抛出js-error异常。 3218因该回调调用时网页还未加载,无法在回调中使用有关操作网页的接口,例如[zoomIn](./arkts-apis-webview-WebviewController.md#zoomin)、[zoomOut](./arkts-apis-webview-WebviewController.md#zoomout)等,可以使用[loadUrl](./arkts-apis-webview-WebviewController.md#loadurl)、[getWebId](./arkts-apis-webview-WebviewController.md#getwebid)等操作网页不相关的接口。 3219 3220组件生命周期详情可参考[Web组件的生命周期](../../web/web-event-sequence.md)。 3221 3222**系统能力:** SystemCapability.Web.Webview.Core 3223 3224**参数:** 3225 3226| 参数名 | 类型 | 必填 | 说明 | 3227| ------ | ------ | ---- | --------------------- | 3228| callback | () => void | 是 | 当ArkWeb控制器初始化成功时触发的回调。 | 3229 3230**示例:** 3231 3232在该回调中使用loadUrl加载网页 3233 ```ts 3234 // xxx.ets 3235 import { webview } from '@kit.ArkWeb'; 3236 3237 @Entry 3238 @Component 3239 struct WebComponent { 3240 controller: webview.WebviewController = new webview.WebviewController(); 3241 3242 build() { 3243 Column() { 3244 Web({ src: '', controller: this.controller }) 3245 .onControllerAttached(() => { 3246 this.controller.loadUrl($rawfile("index.html")); 3247 }) 3248 } 3249 } 3250 } 3251 ``` 3252 3253在该回调中使用getWebId 3254 ```ts 3255 // xxx.ets 3256 import { webview } from '@kit.ArkWeb'; 3257 import { BusinessError } from '@kit.BasicServicesKit'; 3258 3259 @Entry 3260 @Component 3261 struct WebComponent { 3262 controller: webview.WebviewController = new webview.WebviewController(); 3263 3264 build() { 3265 Column() { 3266 Web({ src: $rawfile("index.html"), controller: this.controller }) 3267 .onControllerAttached(() => { 3268 try { 3269 let id = this.controller.getWebId(); 3270 console.info("id: " + id); 3271 } catch (error) { 3272 let code = (error as BusinessError).code; 3273 let message = (error as BusinessError).message; 3274 console.error(`ErrorCode: ${code}, Message: ${message}`); 3275 } 3276 }) 3277 } 3278 } 3279 } 3280 ``` 3281 加载的html文件。 3282 ```html 3283 <!-- index.html --> 3284 <!DOCTYPE html> 3285 <html> 3286 <body> 3287 <p>Hello World</p> 3288 </body> 3289 </html> 3290 ``` 3291 3292## onNavigationEntryCommitted<sup>11+</sup> 3293 3294onNavigationEntryCommitted(callback: [OnNavigationEntryCommittedCallback](./arkts-basic-components-web-t.md#onnavigationentrycommittedcallback11)) 3295 3296当网页跳转提交时触发该回调。 3297 3298**系统能力:** SystemCapability.Web.Webview.Core 3299 3300**参数:** 3301 3302| 参数名 | 类型 | 必填 | 说明 | 3303| ------ | ------ | ---- | --------------------- | 3304| callback | [OnNavigationEntryCommittedCallback](./arkts-basic-components-web-t.md#onnavigationentrycommittedcallback11) | 是 | 网页跳转提交时触发的回调。 | 3305 3306**示例:** 3307 3308 ```ts 3309 // xxx.ets 3310 import { webview } from '@kit.ArkWeb'; 3311 3312 @Entry 3313 @Component 3314 struct WebComponent { 3315 controller: webview.WebviewController = new webview.WebviewController(); 3316 3317 build() { 3318 Column() { 3319 Web({ src: 'www.example.com', controller: this.controller }) 3320 .onNavigationEntryCommitted((details) => { 3321 console.info("onNavigationEntryCommitted: [isMainFrame]= " + details.isMainFrame + 3322 ", [isSameDocument]=" + details.isSameDocument + 3323 ", [didReplaceEntry]=" + details.didReplaceEntry + 3324 ", [navigationType]=" + details.navigationType + 3325 ", [url]=" + details.url); 3326 }) 3327 } 3328 } 3329 } 3330 ``` 3331 3332## onSafeBrowsingCheckResult<sup>11+</sup> 3333 3334onSafeBrowsingCheckResult(callback: OnSafeBrowsingCheckResultCallback) 3335 3336收到网站安全风险检查结果时触发的回调。 3337 3338**系统能力:** SystemCapability.Web.Webview.Core 3339 3340**参数:** 3341 3342| 参数名 | 类型 | 必填 | 说明 | 3343| ------ | ------ | ---- | --------------------- | 3344| callback | [OnSafeBrowsingCheckResultCallback](./arkts-basic-components-web-t.md#onsafebrowsingcheckresultcallback11) | 是 | 收到网站安全风险检查结果时触发的回调。| 3345 3346**示例:** 3347 3348 ```ts 3349 // xxx.ets 3350 import { webview } from '@kit.ArkWeb'; 3351 3352 export enum ThreatType { 3353 UNKNOWN = -1, 3354 THREAT_ILLEGAL = 0, 3355 THREAT_FRAUD = 1, 3356 THREAT_RISK = 2, 3357 THREAT_WARNING = 3, 3358 } 3359 3360 export class OnSafeBrowsingCheckResultCallback { 3361 threatType: ThreatType = ThreatType.UNKNOWN; 3362 } 3363 3364 @Entry 3365 @Component 3366 struct WebComponent { 3367 controller: webview.WebviewController = new webview.WebviewController(); 3368 3369 build() { 3370 Column() { 3371 Web({ src: 'www.example.com', controller: this.controller }) 3372 .onSafeBrowsingCheckResult((callback) => { 3373 let jsonData = JSON.stringify(callback); 3374 let json: OnSafeBrowsingCheckResultCallback = JSON.parse(jsonData); 3375 console.info("onSafeBrowsingCheckResult: [threatType]= " + json.threatType); 3376 }) 3377 } 3378 } 3379 } 3380 ``` 3381 3382## onNativeEmbedLifecycleChange<sup>11+</sup> 3383 3384onNativeEmbedLifecycleChange(callback: (event: NativeEmbedDataInfo) => void) 3385 3386当同层标签生命周期变化时触发该回调。 3387 3388**系统能力:** SystemCapability.Web.Webview.Core 3389 3390**参数:** 3391 3392| 参数名 | 类型 | 必填 | 说明 | 3393| ------ | ------ | ---- | --------------------- | 3394| callback | (event: [NativeEmbedDataInfo](./arkts-basic-components-web-i.md#nativeembeddatainfo11)) => void | 是 | 同层标签生命周期变化时触发该回调。 | 3395 3396**示例:** 3397 3398```ts 3399// EntryAbility.ets 3400 3401import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit'; 3402import { hilog } from '@kit.PerformanceAnalysisKit'; 3403import { window } from '@kit.ArkUI'; 3404import { webview } from '@kit.ArkWeb'; 3405 3406export default class EntryAbility extends UIAbility { 3407 onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { 3408 hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); 3409 // API12新增:开启同层渲染BFCache开关 3410 let features = new webview.BackForwardCacheSupportedFeatures(); 3411 features.nativeEmbed = true; 3412 features.mediaTakeOver = true; 3413 webview.WebviewController.enableBackForwardCache(features); 3414 webview.WebviewController.initializeWebEngine(); 3415 } 3416 3417 onDestroy(): void { 3418 hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); 3419 } 3420 3421 onWindowStageCreate(windowStage: window.WindowStage): void { 3422 // Main window is created, set main page for this ability 3423 hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); 3424 3425 windowStage.loadContent('pages/Index', (err) => { 3426 if (err.code) { 3427 hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); 3428 return; 3429 } 3430 hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.'); 3431 }); 3432 } 3433 3434 onWindowStageDestroy(): void { 3435 // Main window is destroyed, release UI related resources 3436 hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); 3437 } 3438 3439 onForeground(): void { 3440 // Ability has brought to foreground 3441 hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); 3442 } 3443 3444 onBackground(): void { 3445 // Ability has back to background 3446 hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); 3447 } 3448} 3449``` 3450 3451 ```ts 3452 // xxx.ets 3453 import { webview } from '@kit.ArkWeb'; 3454 import { BusinessError } from '@kit.BasicServicesKit'; 3455 3456 @Entry 3457 @Component 3458 struct WebComponent { 3459 @State embedStatus: string = ''; 3460 controller: webview.WebviewController = new webview.WebviewController(); 3461 3462 build() { 3463 Column() { 3464 // 默认行为:点击按钮跳转页面,关闭index页面,使同层标签销毁。 3465 // API12新增:使能同层渲染所在的页面支持BFCache后,点击按钮跳转页面,关闭index页面,使同层标签进入BFCache。 3466 Button('Destroy') 3467 .onClick(() => { 3468 try { 3469 this.controller.loadUrl("www.example.com"); 3470 } catch (error) { 3471 console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`); 3472 } 3473 }) 3474 3475 // API12新增:使能同层渲染所在的页面支持BFCache后,点击按钮返回页面,使同层标签离开BFCache。 3476 Button('backward') 3477 .onClick(() => { 3478 try { 3479 this.controller.backward(); 3480 } catch (error) { 3481 console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`); 3482 } 3483 }) 3484 3485 // API12新增:使能同层渲染所在的页面支持BFCache后,点击按钮前进页面,使同层标签进入BFCache。 3486 Button('forward') 3487 .onClick(() => { 3488 try { 3489 this.controller.forward(); 3490 } catch (error) { 3491 console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`); 3492 } 3493 }) 3494 3495 3496 // API12新增同层标签进入离开BFCache状态:非http与https协议加载的网页,Web内核不支持进入BFCache; 3497 // 因此如果要测试ENTER_BFCACHE/LEAVE_BFCACHE状态,需要将index.html放到Web服务器上,使用http或者https协议加载,如: 3498 // Web({ src: "http://xxxx/index.html", controller: this.controller }) 3499 Web({ src: $rawfile("index.html"), controller: this.controller }) 3500 .enableNativeEmbedMode(true) 3501 .onNativeEmbedLifecycleChange((event) => { 3502 // 当加载页面中有同层标签会触发Create。 3503 if (event.status == NativeEmbedStatus.CREATE) { 3504 this.embedStatus = 'Create'; 3505 } 3506 // 当页面中同层标签移动或者缩放时会触发Update。 3507 if (event.status == NativeEmbedStatus.UPDATE) { 3508 this.embedStatus = 'Update'; 3509 } 3510 // 退出页面时会触发Destroy。 3511 if (event.status == NativeEmbedStatus.DESTROY) { 3512 this.embedStatus = 'Destroy'; 3513 } 3514 // 同层标签所在的页面进入BFCache时,会触发Enter BFCache。 3515 if (event.status == NativeEmbedStatus.ENTER_BFCACHE) { 3516 this.embedStatus = 'Enter BFCache'; 3517 } 3518 // 同层标签所在的页面离开BFCache时,会触发Leave BFCache。 3519 if (event.status == NativeEmbedStatus.LEAVE_BFCACHE) { 3520 this.embedStatus = 'Leave BFCache'; 3521 } 3522 console.info("status = " + this.embedStatus); 3523 console.info("surfaceId = " + event.surfaceId); 3524 console.info("embedId = " + event.embedId); 3525 if (event.info) { 3526 console.info("id = " + event.info.id); 3527 console.info("type = " + event.info.type); 3528 console.info("src = " + event.info.src); 3529 console.info("width = " + event.info.width); 3530 console.info("height = " + event.info.height); 3531 console.info("url = " + event.info.url); 3532 } 3533 }) 3534 } 3535 } 3536 } 3537 ``` 3538 3539 加载的html文件 3540 ```html 3541 <!--index.html--> 3542 <!DOCTYPE html> 3543 <html> 3544 <head> 3545 <title>同层渲染测试html</title> 3546 <meta name="viewport"> 3547 </head> 3548 <body> 3549 <div> 3550 <div id="bodyId"> 3551 <embed id="nativeButton" type = "native/button" width="800" height="800" src="test? params1=1" style = "background-color:red"/> 3552 </div> 3553 </div> 3554 </body> 3555 </html> 3556 ``` 3557 3558## onNativeEmbedGestureEvent<sup>11+</sup> 3559 3560onNativeEmbedGestureEvent(callback: (event: NativeEmbedTouchInfo) => void) 3561 3562当手指触摸到同层标签时触发该回调。 3563 3564**系统能力:** SystemCapability.Web.Webview.Core 3565 3566**参数:** 3567 3568| 参数名 | 类型 | 必填 | 说明 | 3569| ------ | ------ | ---- | --------------------- | 3570| callback | (event: [NativeEmbedTouchInfo](./arkts-basic-components-web-i.md#nativeembedtouchinfo11)) => void | 是 | 手指触摸到同层标签时触发该回调。 | 3571 3572**示例:** 3573 3574 ```ts 3575 // xxx.ets 3576 import { webview } from '@kit.ArkWeb'; 3577 import { NodeController, BuilderNode, NodeRenderType, FrameNode, UIContext } from "@kit.ArkUI"; 3578 3579 declare class Params { 3580 text: string; 3581 width: number; 3582 height: number; 3583 } 3584 3585 declare class NodeControllerParams { 3586 surfaceId: string; 3587 renderType: NodeRenderType; 3588 width: number; 3589 height: number; 3590 } 3591 3592 class MyNodeController extends NodeController { 3593 private rootNode: BuilderNode<[Params]> | undefined | null; 3594 private surfaceId_: string = ""; 3595 private renderType_: NodeRenderType = NodeRenderType.RENDER_TYPE_DISPLAY; 3596 private width_: number = 0; 3597 private height_: number = 0; 3598 3599 setRenderOption(params: NodeControllerParams) { 3600 this.surfaceId_ = params.surfaceId; 3601 this.renderType_ = params.renderType; 3602 this.width_ = params.width; 3603 this.height_ = params.height; 3604 } 3605 3606 makeNode(uiContext: UIContext): FrameNode | null { 3607 this.rootNode = new BuilderNode(uiContext, { surfaceId: this.surfaceId_, type: this.renderType_ }); 3608 this.rootNode.build(wrapBuilder(ButtonBuilder), { text: "myButton", width: this.width_, height: this.height_ }); 3609 return this.rootNode.getFrameNode(); 3610 } 3611 3612 postEvent(event: TouchEvent | undefined): boolean { 3613 return this.rootNode?.postTouchEvent(event) as boolean; 3614 } 3615 } 3616 3617 @Component 3618 struct ButtonComponent { 3619 @Prop params: Params; 3620 @State bkColor: Color = Color.Red; 3621 3622 build() { 3623 Column() { 3624 Button(this.params.text) 3625 .height(50) 3626 .width(200) 3627 .border({ width: 2, color: Color.Red }) 3628 .backgroundColor(this.bkColor) 3629 3630 } 3631 .width(this.params.width) 3632 .height(this.params.height) 3633 } 3634 } 3635 3636 @Builder 3637 function ButtonBuilder(params: Params) { 3638 ButtonComponent({ params: params }) 3639 .backgroundColor(Color.Green) 3640 } 3641 3642 @Entry 3643 @Component 3644 struct WebComponent { 3645 @State eventType: string = ''; 3646 controller: webview.WebviewController = new webview.WebviewController(); 3647 private nodeController: MyNodeController = new MyNodeController(); 3648 uiContext: UIContext = this.getUIContext(); 3649 3650 build() { 3651 Column() { 3652 Stack() { 3653 NodeContainer(this.nodeController) 3654 Web({ src: $rawfile("index.html"), controller: this.controller }) 3655 .enableNativeEmbedMode(true) 3656 .onNativeEmbedLifecycleChange((embed) => { 3657 if (embed.status == NativeEmbedStatus.CREATE) { 3658 this.nodeController.setRenderOption({ 3659 surfaceId: embed.surfaceId as string, 3660 renderType: NodeRenderType.RENDER_TYPE_TEXTURE, 3661 width: this.uiContext!.px2vp(embed.info?.width), 3662 height: this.uiContext!.px2vp(embed.info?.height) 3663 }); 3664 this.nodeController.rebuild(); 3665 } 3666 }) 3667 .onNativeEmbedGestureEvent((event) => { 3668 if (event && event.touchEvent) { 3669 if (event.touchEvent.type == TouchType.Down) { 3670 this.eventType = 'Down' 3671 } 3672 if (event.touchEvent.type == TouchType.Up) { 3673 this.eventType = 'Up' 3674 } 3675 if (event.touchEvent.type == TouchType.Move) { 3676 this.eventType = 'Move' 3677 } 3678 if (event.touchEvent.type == TouchType.Cancel) { 3679 this.eventType = 'Cancel' 3680 } 3681 let ret = this.nodeController.postEvent(event.touchEvent) 3682 if (event.result) { 3683 event.result.setGestureEventResult(ret, true); 3684 } 3685 console.info("embedId = " + event.embedId); 3686 console.info("touchType = " + this.eventType); 3687 console.info("x = " + event.touchEvent.touches[0].x); 3688 console.info("y = " + event.touchEvent.touches[0].y); 3689 console.info("Component globalPos:(" + event.touchEvent.target.area.globalPosition.x + "," + event.touchEvent.target.area.globalPosition.y + ")"); 3690 console.info("width = " + event.touchEvent.target.area.width); 3691 console.info("height = " + event.touchEvent.target.area.height); 3692 } 3693 }) 3694 } 3695 } 3696 } 3697 } 3698 ``` 3699加载的html文件 3700 ```html 3701 <!--index.html--> 3702 <!DOCTYPE html> 3703 <html> 3704 <head> 3705 <title>同层渲染测试html</title> 3706 <meta name="viewport"> 3707 </head> 3708 <body> 3709 <div> 3710 <div id="bodyId"> 3711 <embed id="nativeButton" type = "native/button" width="800" height="800" src="test?params1=1" style = "background-color:red"/> 3712 </div> 3713 </div> 3714 </body> 3715 </html> 3716 ``` 3717 3718## onIntelligentTrackingPreventionResult<sup>12+</sup> 3719 3720onIntelligentTrackingPreventionResult(callback: OnIntelligentTrackingPreventionCallback) 3721 3722智能防跟踪功能使能时,当追踪者cookie被拦截时触发该回调。 3723 3724**系统能力:** SystemCapability.Web.Webview.Core 3725 3726**参数:** 3727 3728| 参数名 | 类型 | 必填 | 说明 | 3729| ------ | ------ | ---- | --------------------- | 3730| callback | [OnIntelligentTrackingPreventionCallback](./arkts-basic-components-web-t.md#onintelligenttrackingpreventioncallback12) | 是 | 智能防跟踪功能使能时,当追踪者cookie被拦截时触发的回调。 | 3731 3732**示例:** 3733 3734 ```ts 3735 // xxx.ets 3736 import { webview } from '@kit.ArkWeb'; 3737 import { BusinessError } from '@kit.BasicServicesKit'; 3738 3739 @Entry 3740 @Component 3741 struct WebComponent { 3742 controller: webview.WebviewController = new webview.WebviewController(); 3743 3744 build() { 3745 Column() { 3746 // 需要打开智能防跟踪功能,才会触发onIntelligentTrackingPreventionResult回调 3747 Button('enableIntelligentTrackingPrevention') 3748 .onClick(() => { 3749 try { 3750 this.controller.enableIntelligentTrackingPrevention(true); 3751 } catch (error) { 3752 console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`); 3753 } 3754 }) 3755 Web({ src: 'www.example.com', controller: this.controller }) 3756 .onIntelligentTrackingPreventionResult((details) => { 3757 console.info("onIntelligentTrackingPreventionResult: [websiteHost]= " + details.host + 3758 ", [trackerHost]=" + details.trackerHost); 3759 }) 3760 } 3761 } 3762 } 3763 ``` 3764 3765## onOverrideUrlLoading<sup>12+</sup> 3766 3767onOverrideUrlLoading(callback: OnOverrideUrlLoadingCallback) 3768 3769当URL将要加载到当前Web中时触发该回调,让宿主应用程序有机会获得控制权,判断是否阻止Web加载URL。 3770 3771> **说明:** 3772> 3773> - POST请求不会触发该回调。 3774> - iframe加载HTTP(s)协议或about:blank时不会触发该回调,而加载非HTTP(s)协议的跳转会触发;调用loadUrl(url: string)主动触发的跳转不会触发该回调。 3775> - 不要在回调中使用相同的URL调用loadUrl(url: string)方法,然后返回true。 这样会不必要地中止当前加载,并用相同的URL发起一次新的加载。 要继续加载当前请求URL的正确做法是直接返回false,而不是调用loadUrl(url: string)。 3776 3777**系统能力:** SystemCapability.Web.Webview.Core 3778 3779**参数:** 3780 3781| 参数名 | 类型 | 必填 | 说明 | 3782| ------ | ------ | ---- | --------------------- | 3783| callback | [OnOverrideUrlLoadingCallback](./arkts-basic-components-web-t.md#onoverrideurlloadingcallback12) | 是 | onOverrideUrlLoading的回调。<br>返回值boolean。返回ture表示中止加载URL,返回false表示继续在Web中加载URL | 3784 3785**示例:** 3786 3787 ```ts 3788 // xxx.ets 3789 import { webview } from '@kit.ArkWeb'; 3790 3791 @Entry 3792 @Component 3793 struct WebComponent { 3794 controller: webview.WebviewController = new webview.WebviewController(); 3795 3796 build() { 3797 Column() { 3798 Web({ src: $rawfile("index.html"), controller: this.controller }) 3799 .onOverrideUrlLoading((webResourceRequest: WebResourceRequest) => { 3800 if (webResourceRequest && webResourceRequest.getRequestUrl() == "about:blank") { 3801 return true; 3802 } 3803 return false; 3804 }) 3805 } 3806 } 3807 } 3808 ``` 3809 3810 加载的html文件。 3811 ```html 3812 <!--index.html--> 3813 <!DOCTYPE html> 3814 <html> 3815 <head> 3816 <title>测试网页</title> 3817 </head> 3818 <body> 3819 <h1>onOverrideUrlLoading Demo</h1> 3820 <a href="about:blank">Click here</a>// 访问about:blank。 3821 </body> 3822 </html> 3823 ``` 3824 3825## onViewportFitChanged<sup>12+</sup> 3826 3827onViewportFitChanged(callback: OnViewportFitChangedCallback) 3828 3829网页meta中viewport-fit配置项更改时触发该回调,应用可在此回调中自适应布局视口。 3830 3831**系统能力:** SystemCapability.Web.Webview.Core 3832 3833**参数:** 3834 3835| 参数名 | 类型 | 必填 | 说明 | 3836| ------ | ------ | ---- | --------------------- | 3837| callback | [OnViewportFitChangedCallback](./arkts-basic-components-web-t.md#onviewportfitchangedcallback12) | 是 | 网页meta中viewport-fit配置项更改时触发的回调。 | 3838 3839**示例:** 3840 3841 ```ts 3842 // xxx.ets 3843 import { webview } from '@kit.ArkWeb'; 3844 3845 @Entry 3846 @Component 3847 struct WebComponent { 3848 controller: webview.WebviewController = new webview.WebviewController(); 3849 3850 build() { 3851 Column() { 3852 Web({ src: $rawfile('index.html'), controller: this.controller }) 3853 .onViewportFitChanged((data) => { 3854 let jsonData = JSON.stringify(data); 3855 let viewportFit: ViewportFit = JSON.parse(jsonData).viewportFit; 3856 if (viewportFit === ViewportFit.COVER) { 3857 // index.html网页支持沉浸式布局,可调用expandSafeArea调整web控件布局视口覆盖避让区域(状态栏或导航条)。 3858 } else if (viewportFit === ViewportFit.CONTAINS) { 3859 // index.html网页不支持沉浸式布局,可调用expandSafeArea调整web控件布局视口为安全区域。 3860 } else { 3861 // 默认值,可不作处理。 3862 } 3863 }) 3864 } 3865 } 3866 } 3867 ``` 3868 3869 加载的html文件。 3870 ```html 3871 <!-- index.html --> 3872 <!DOCTYPE html> 3873 <html> 3874 <head> 3875 <meta name="viewport" content="width=device-width,viewport-fit=cover"> 3876 </head> 3877 <body> 3878 <div style="position: absolute; bottom: 0; margin-bottom: env(safe-area-inset-bottom)"></div> 3879 </body> 3880 </html> 3881 ``` 3882 3883## onInterceptKeyboardAttach<sup>12+</sup> 3884 3885onInterceptKeyboardAttach(callback: WebKeyboardCallback) 3886 3887网页中可编辑元素(如input标签)拉起软键盘之前会回调该接口,应用可以使用该接口拦截系统软键盘的弹出,配置应用定制的软键盘(应用根据该接口可以决定使用系统默认软键盘/定制enter键的系统软键盘/全部由应用自定义的软键盘)。 3888 3889**系统能力:** SystemCapability.Web.Webview.Core 3890 3891**参数:** 3892 3893| 参数名 | 类型 | 必填 | 说明 | 3894| ------ | ------ | ---- | --------------------- | 3895| callback | [WebKeyboardCallback](./arkts-basic-components-web-t.md#webkeyboardcallback12) | 是 | 拦截网页拉起软键盘回调。 | 3896 3897**示例:** 3898 3899 ```ts 3900 // xxx.ets 3901 import { webview } from '@kit.ArkWeb'; 3902 import { inputMethodEngine } from '@kit.IMEKit'; 3903 3904 @Entry 3905 @Component 3906 struct WebComponent { 3907 controller: webview.WebviewController = new webview.WebviewController(); 3908 webKeyboardController: WebKeyboardController = new WebKeyboardController() 3909 inputAttributeMap: Map<string, number> = new Map([ 3910 ['UNSPECIFIED', inputMethodEngine.ENTER_KEY_TYPE_UNSPECIFIED], 3911 ['GO', inputMethodEngine.ENTER_KEY_TYPE_GO], 3912 ['SEARCH', inputMethodEngine.ENTER_KEY_TYPE_SEARCH], 3913 ['SEND', inputMethodEngine.ENTER_KEY_TYPE_SEND], 3914 ['NEXT', inputMethodEngine.ENTER_KEY_TYPE_NEXT], 3915 ['DONE', inputMethodEngine.ENTER_KEY_TYPE_DONE], 3916 ['PREVIOUS', inputMethodEngine.ENTER_KEY_TYPE_PREVIOUS] 3917 ]) 3918 3919 /** 3920 * 自定义键盘组件Builder 3921 */ 3922 @Builder 3923 customKeyboardBuilder() { 3924 // 这里实现自定义键盘组件,对接WebKeyboardController实现输入、删除、关闭等操作。 3925 Row() { 3926 Text("完成") 3927 .fontSize(20) 3928 .fontColor(Color.Blue) 3929 .onClick(() => { 3930 this.webKeyboardController.close(); 3931 }) 3932 // 插入字符。 3933 Button("insertText").onClick(() => { 3934 this.webKeyboardController.insertText('insert '); 3935 }).margin({ 3936 bottom: 200, 3937 }) 3938 // 从后往前删除length参数指定长度的字符。 3939 Button("deleteForward").onClick(() => { 3940 this.webKeyboardController.deleteForward(1); 3941 }).margin({ 3942 bottom: 200, 3943 }) 3944 // 从前往后删除length参数指定长度的字符。 3945 Button("deleteBackward").onClick(() => { 3946 this.webKeyboardController.deleteBackward(1); 3947 }).margin({ 3948 left: -220, 3949 }) 3950 // 插入功能按键。 3951 Button("sendFunctionKey").onClick(() => { 3952 this.webKeyboardController.sendFunctionKey(6); 3953 }) 3954 } 3955 } 3956 3957 build() { 3958 Column() { 3959 Web({ src: $rawfile('index.html'), controller: this.controller }) 3960 .onInterceptKeyboardAttach((KeyboardCallbackInfo) => { 3961 // option初始化,默认使用系统默认键盘 3962 let option: WebKeyboardOptions = { 3963 useSystemKeyboard: true, 3964 }; 3965 if (!KeyboardCallbackInfo) { 3966 return option; 3967 } 3968 3969 // 保存WebKeyboardController,使用自定义键盘时候,需要使用该handler控制输入、删除、软键盘关闭等行为 3970 this.webKeyboardController = KeyboardCallbackInfo.controller 3971 let attributes: Record<string, string> = KeyboardCallbackInfo.attributes 3972 // 遍历attributes 3973 let attributeKeys = Object.keys(attributes) 3974 for (let i = 0; i < attributeKeys.length; i++) { 3975 console.log('WebCustomKeyboard key = ' + attributeKeys[i] + ', value = ' + attributes[attributeKeys[i]]) 3976 } 3977 3978 if (attributes) { 3979 if (attributes['data-keyboard'] == 'customKeyboard') { 3980 // 根据html可编辑元素的属性,判断使用不同的软键盘,例如这里如果属性包含有data-keyboard,且值为customKeyboard,则使用自定义键盘 3981 console.info('WebCustomKeyboard use custom keyboard') 3982 option.useSystemKeyboard = false; 3983 // 设置自定义键盘builder 3984 option.customKeyboard = () => { 3985 this.customKeyboardBuilder() 3986 } 3987 return option; 3988 } 3989 3990 if (attributes['keyboard-return'] != undefined) { 3991 // 根据html可编辑元素的属性,判断使用不同的软键盘,例如这里如果属性包含有keyboard-return,使用系统键盘,并且指定系统软键盘enterKey类型 3992 option.useSystemKeyboard = true; 3993 let enterKeyType: number | undefined = this.inputAttributeMap.get(attributes['keyboard-return']) 3994 if (enterKeyType != undefined) { 3995 option.enterKeyType = enterKeyType 3996 } 3997 return option; 3998 } 3999 } 4000 4001 return option; 4002 }) 4003 } 4004 } 4005 } 4006 ``` 4007 4008 加载的html文件。 4009 ```html 4010 <!-- index.html --> 4011 <!DOCTYPE html> 4012 <html> 4013 4014 <head> 4015 <meta charset="utf-8"> 4016 <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0"> 4017 </head> 4018 4019 <body> 4020 4021 <p style="font-size:12px">input标签,原有默认行为:</p> 4022 <input type="text" style="width: 300px; height: 20px"><br> 4023 <hr style="height:2px;border-width:0;color:gray;background-color:gray"> 4024 4025 <p style="font-size:12px">input标签,系统键盘自定义enterKeyType属性 enter key UNSPECIFIED:</p> 4026 <input type="text" keyboard-return="UNSPECIFIED" style="width: 300px; height: 20px"><br> 4027 <hr style="height:2px;border-width:0;color:gray;background-color:gray"> 4028 4029 <p style="font-size:12px">input标签,系统键盘自定义enterKeyType属性 enter key GO:</p> 4030 <input type="text" keyboard-return="GO" style="width: 300px; height: 20px"><br> 4031 <hr style="height:2px;border-width:0;color:gray;background-color:gray"> 4032 4033 <p style="font-size:12px">input标签,系统键盘自定义enterKeyType属性 enter key SEARCH:</p> 4034 <input type="text" keyboard-return="SEARCH" style="width: 300px; height: 20px"><br> 4035 <hr style="height:2px;border-width:0;color:gray;background-color:gray"> 4036 4037 <p style="font-size:12px">input标签,系统键盘自定义enterKeyType属性 enter key SEND:</p> 4038 <input type="text" keyboard-return="SEND" style="width: 300px; height: 20px"><br> 4039 <hr style="height:2px;border-width:0;color:gray;background-color:gray"> 4040 4041 <p style="font-size:12px">input标签,系统键盘自定义enterKeyType属性 enter key NEXT:</p> 4042 <input type="text" keyboard-return="NEXT" style="width: 300px; height: 20px"><br> 4043 <hr style="height:2px;border-width:0;color:gray;background-color:gray"> 4044 4045 <p style="font-size:12px">input标签,系统键盘自定义enterKeyType属性 enter key DONE:</p> 4046 <input type="text" keyboard-return="DONE" style="width: 300px; height: 20px"><br> 4047 <hr style="height:2px;border-width:0;color:gray;background-color:gray"> 4048 4049 <p style="font-size:12px">input标签,系统键盘自定义enterKeyType属性 enter key PREVIOUS:</p> 4050 <input type="text" keyboard-return="PREVIOUS" style="width: 300px; height: 20px"><br> 4051 <hr style="height:2px;border-width:0;color:gray;background-color:gray"> 4052 4053 <p style="font-size:12px">input标签,应用自定义键盘:</p> 4054 <input type="text" data-keyboard="customKeyboard" style="width: 300px; height: 20px"><br> 4055 4056 </body> 4057 4058 </html> 4059 ``` 4060 4061## onNativeEmbedVisibilityChange<sup>12+</sup> 4062 4063onNativeEmbedVisibilityChange(callback: OnNativeEmbedVisibilityChangeCallback) 4064 4065当网页中同层标签(例如<embed\>标签或<object\>标签)在视口内的可见性发生变化时,将触发该回调。同层标签默认不可见,若在页面首次加载时已可见,则会上报;若不可见,则不会上报。同层标签全部不可见才视为不可见,部分可见或全部可见则视为可见。若要获取因同层标签CSS属性(包括visibility、display以及尺寸变化)导致的可见状态变化,需配置[nativeEmbedOptions](./arkts-basic-components-web-attributes.md#nativeembedoptions16),并将[EmbedOptions](./arkts-basic-components-web-i.md#embedoptions16)中的supportCssDisplayChange参数设为true。 4066 4067**系统能力:** SystemCapability.Web.Webview.Core 4068 4069**参数:** 4070 4071| 参数名 | 类型 | 必填 | 说明 | 4072| ------ | ------ | ---- | --------------------- | 4073| callback | [OnNativeEmbedVisibilityChangeCallback](./arkts-basic-components-web-t.md#onnativeembedvisibilitychangecallback12) | 是 | 同层标签可见性变化时触发该回调。 | 4074 4075**示例:** 4076 4077 ```ts 4078 // xxx.ets 4079 import { webview } from '@kit.ArkWeb'; 4080 import { NodeController, BuilderNode, NodeRenderType, FrameNode, UIContext } from "@kit.ArkUI"; 4081 4082 declare class Params { 4083 text: string; 4084 width: number; 4085 height: number; 4086 } 4087 4088 declare class NodeControllerParams { 4089 surfaceId: string; 4090 renderType: NodeRenderType; 4091 width: number; 4092 height: number; 4093 } 4094 4095 class MyNodeController extends NodeController { 4096 private rootNode: BuilderNode<[Params]> | undefined | null; 4097 private surfaceId_: string = ""; 4098 private renderType_: NodeRenderType = NodeRenderType.RENDER_TYPE_DISPLAY; 4099 private width_: number = 0; 4100 private height_: number = 0; 4101 4102 setRenderOption(params: NodeControllerParams) { 4103 this.surfaceId_ = params.surfaceId; 4104 this.renderType_ = params.renderType; 4105 this.width_ = params.width; 4106 this.height_ = params.height; 4107 } 4108 4109 makeNode(uiContext: UIContext): FrameNode | null { 4110 this.rootNode = new BuilderNode(uiContext, { surfaceId: this.surfaceId_, type: this.renderType_ }); 4111 this.rootNode.build(wrapBuilder(ButtonBuilder), { text: "myButton", width: this.width_, height: this.height_ }); 4112 return this.rootNode.getFrameNode(); 4113 } 4114 4115 postEvent(event: TouchEvent | undefined): boolean { 4116 return this.rootNode?.postTouchEvent(event) as boolean; 4117 } 4118 } 4119 4120 @Component 4121 struct ButtonComponent { 4122 @Prop params: Params; 4123 @State bkColor: Color = Color.Red; 4124 4125 build() { 4126 Column() { 4127 Button(this.params.text) 4128 .height(50) 4129 .width(200) 4130 .border({ width: 2, color: Color.Red }) 4131 .backgroundColor(this.bkColor) 4132 4133 } 4134 .width(this.params.width) 4135 .height(this.params.height) 4136 } 4137 } 4138 4139 @Builder 4140 function ButtonBuilder(params: Params) { 4141 ButtonComponent({ params: params }) 4142 .backgroundColor(Color.Green) 4143 } 4144 4145 @Entry 4146 @Component 4147 struct WebComponent { 4148 @State embedVisibility: string = ''; 4149 controller: webview.WebviewController = new webview.WebviewController(); 4150 private nodeController: MyNodeController = new MyNodeController(); 4151 uiContext: UIContext = this.getUIContext(); 4152 4153 build() { 4154 Column() { 4155 Stack() { 4156 NodeContainer(this.nodeController) 4157 Web({ src: $rawfile("index.html"), controller: this.controller }) 4158 .enableNativeEmbedMode(true) 4159 .onNativeEmbedLifecycleChange((embed) => { 4160 if (embed.status == NativeEmbedStatus.CREATE) { 4161 this.nodeController.setRenderOption({ 4162 surfaceId: embed.surfaceId as string, 4163 renderType: NodeRenderType.RENDER_TYPE_TEXTURE, 4164 width: this.uiContext!.px2vp(embed.info?.width), 4165 height: this.uiContext!.px2vp(embed.info?.height) 4166 }); 4167 this.nodeController.rebuild(); 4168 } 4169 }) 4170 .onNativeEmbedVisibilityChange((embed) => { 4171 if (embed.visibility) { 4172 this.embedVisibility = 'Visible'; 4173 } else { 4174 this.embedVisibility = 'Hidden'; 4175 } 4176 console.info("embedId = " + embed.embedId); 4177 console.info("visibility = " + embed.visibility); 4178 }) 4179 } 4180 } 4181 } 4182 } 4183 ``` 4184 4185 加载的html文件 4186 ```html 4187 <!-- index.html --> 4188 <!DOCTYPE html> 4189 <html> 4190 <head> 4191 <title>同层渲染测试html</title> 4192 <meta name="viewport"> 4193 </head> 4194 <body> 4195 <div> 4196 <div id="bodyId"> 4197 <embed id="nativeButton" type = "native/button" width="800" height="800" src="test?params1=1" style = "background-color:red"/> 4198 </div> 4199 </div> 4200 </body> 4201 </html> 4202 ``` 4203 4204## onNativeEmbedMouseEvent<sup>20+</sup> 4205 4206onNativeEmbedMouseEvent(callback: MouseInfoCallback) 4207 4208在同层标签上执行以下行为时触发该回调: 4209 4210- 使用鼠标左键、中键、右键进行点击或长按。 4211- 使用触摸板进行对应鼠标左键、中键、右键点击长按的操作。 4212 4213 4214**系统能力:** SystemCapability.Web.Webview.Core 4215 4216**参数:** 4217 4218| 参数名 | 类型 | 必填 | 说明 | 4219| ------ | ------ | ---- | --------------------- | 4220| callback | [MouseInfoCallback](./arkts-basic-components-web-t.md#mouseinfocallback20) | 是 | 当鼠标/触摸板点击到同层标签时触发该回调。 | 4221 4222**示例:** 4223 4224 ```ts 4225 // xxx.ets 4226 import { webview } from '@kit.ArkWeb'; 4227 import { NodeController, BuilderNode, NodeRenderType, FrameNode, UIContext } from "@kit.ArkUI"; 4228 4229 declare class Params { 4230 text: string; 4231 width: number; 4232 height: number; 4233 } 4234 4235 declare class NodeControllerParams { 4236 surfaceId: string; 4237 renderType: NodeRenderType; 4238 width: number; 4239 height: number; 4240 } 4241 4242 class MyNodeController extends NodeController { 4243 private rootNode: BuilderNode<[Params]> | undefined | null; 4244 private surfaceId_: string = ""; 4245 private renderType_: NodeRenderType = NodeRenderType.RENDER_TYPE_DISPLAY; 4246 private width_: number = 0; 4247 private height_: number = 0; 4248 4249 setRenderOption(params: NodeControllerParams) { 4250 this.surfaceId_ = params.surfaceId; 4251 this.renderType_ = params.renderType; 4252 this.width_ = params.width; 4253 this.height_ = params.height; 4254 } 4255 4256 makeNode(uiContext: UIContext): FrameNode | null { 4257 this.rootNode = new BuilderNode(uiContext, { surfaceId: this.surfaceId_, type: this.renderType_ }); 4258 this.rootNode.build(wrapBuilder(ButtonBuilder), { text: "myButton", width: this.width_, height: this.height_ }); 4259 return this.rootNode.getFrameNode(); 4260 } 4261 4262 postInputEvent(event: TouchEvent | MouseEvent | undefined): boolean { 4263 return this.rootNode?.postInputEvent(event) as boolean; 4264 } 4265 } 4266 4267 @Component 4268 struct ButtonComponent { 4269 @Prop params: Params; 4270 @State bkColor: Color = Color.Red; 4271 4272 build() { 4273 Column() { 4274 Button(this.params.text) 4275 .height(50) 4276 .width(200) 4277 .border({ width: 2, color: Color.Red }) 4278 .backgroundColor(this.bkColor) 4279 4280 } 4281 .width(this.params.width) 4282 .height(this.params.height) 4283 } 4284 } 4285 4286 @Builder 4287 function ButtonBuilder(params: Params) { 4288 ButtonComponent({ params: params }) 4289 .backgroundColor(Color.Green) 4290 } 4291 4292 @Entry 4293 @Component 4294 struct WebComponent { 4295 @State mouseAction: string = ''; 4296 @State mouseButton: string = ''; 4297 controller: webview.WebviewController = new webview.WebviewController(); 4298 private nodeController: MyNodeController = new MyNodeController(); 4299 uiContext: UIContext = this.getUIContext(); 4300 4301 build() { 4302 Column() { 4303 Stack() { 4304 NodeContainer(this.nodeController) 4305 Web({ src: $rawfile("index.html"), controller: this.controller }) 4306 .enableNativeEmbedMode(true) 4307 .onNativeEmbedLifecycleChange((embed) => { 4308 if (embed.status == NativeEmbedStatus.CREATE) { 4309 this.nodeController.setRenderOption({ 4310 surfaceId: embed.surfaceId as string, 4311 renderType: NodeRenderType.RENDER_TYPE_TEXTURE, 4312 width: this.uiContext!.px2vp(embed.info?.width), 4313 height: this.uiContext!.px2vp(embed.info?.height) 4314 }); 4315 this.nodeController.rebuild(); 4316 } 4317 }) 4318 .onNativeEmbedMouseEvent((event) => { 4319 if (event && event.mouseEvent) { 4320 let ret = this.nodeController.postInputEvent(event.mouseEvent) 4321 if (event.result) { 4322 event.result.setMouseEventResult(ret, true); 4323 } 4324 } 4325 }) 4326 } 4327 } 4328 } 4329 } 4330 ``` 4331加载的html文件 4332 ```html 4333 <!--index.html--> 4334 <!DOCTYPE html> 4335 <html> 4336 <head> 4337 <title>同层渲染测试</title> 4338 <meta name="viewport"> 4339 </head> 4340 <body> 4341 <div> 4342 <div id="bodyId"> 4343 <embed id="nativeButton" type ="native/button" width="800" height="800" style="background-color:red"/> 4344 </div> 4345 </div> 4346 </body> 4347 </html> 4348 ``` 4349 4350## onOverrideErrorPage<sup>20+</sup> 4351 4352onOverrideErrorPage(callback: OnOverrideErrorPageCallback) 4353 4354网页加载遇到错误时触发,只有主资源出错才会回调该接口,可以使用该接口自定义错误展示页。 4355 4356此外,该功能需通过调用[setErrorPageEnabled](./arkts-apis-webview-WebviewController.md#seterrorpageenabled20)接口启用默认错误页后,才会生效。 4357 4358**系统能力:** SystemCapability.Web.Webview.Core 4359 4360**参数:** 4361 4362| 参数名 | 类型 | 必填 | 说明 | 4363| ------- | ---------------------------------------- | ---- | --------------- | 4364| callback | [OnOverrideErrorPageCallback](./arkts-basic-components-web-t.md#onoverrideerrorpagecallback20) | 是 | 网页加载遇到错误时触发。 | 4365 4366**示例:** 4367 4368 ```ts 4369// xxx.ets 4370import { webview } from '@kit.ArkWeb'; 4371@Entry 4372@Component 4373struct WebComponent { 4374 controller: webview.WebviewController = new webview.WebviewController(); 4375 build() { 4376 Column() { 4377 Web({ src: "www.error-test.com", controller: this.controller }) 4378 .onControllerAttached(() => { 4379 this.controller.setErrorPageEnabled(true); 4380 if (!this.controller.getErrorPageEnabled()) { 4381 this.controller.setErrorPageEnabled(true); 4382 } 4383 }) 4384 .onOverrideErrorPage(event => { 4385 let htmlStr = "<html><h1>error occur : "; 4386 htmlStr += event.error.getErrorCode(); 4387 htmlStr += "</h1></html>"; 4388 return htmlStr; 4389 }) 4390 } 4391 } 4392} 4393 ``` 4394 4395## onSslErrorReceive<sup>(deprecated)</sup> 4396 4397onSslErrorReceive(callback: (event?: { handler: Function, error: object }) => void) 4398 4399通知用户加载资源时发生SSL错误。 4400 4401> **说明:** 4402> 4403> 从API version 8开始支持,从API version 9开始废弃。建议使用[onSslErrorEventReceive<sup>9+</sup>](#onsslerroreventreceive9)替代。 4404 4405**系统能力:** SystemCapability.Web.Webview.Core 4406 4407**参数:** 4408 4409| 参数名 | 类型 | 必填 | 说明 | 4410| ------ | ------ | ---- | --------------------- | 4411| callback | (event?: { handler: Function, error: object }) => void | 是 | 当网页检测到SSL错误时触发的回调。 | 4412 4413## onFileSelectorShow<sup>(deprecated)</sup> 4414 4415onFileSelectorShow(callback: (event?: { callback: Function, fileSelector: object }) => void) 4416 4417调用此函数以处理具有“文件”输入类型的HTML表单,以响应用户按下的“选择文件”按钮。 4418 4419> **说明:** 4420> 4421> 从API version 8开始支持,从API version 9开始废弃。建议使用[onShowFileSelector<sup>9+</sup>](#onshowfileselector9)替代。 4422 4423**系统能力:** SystemCapability.Web.Webview.Core 4424 4425**参数:** 4426 4427| 参数名 | 类型 | 必填 | 说明 | 4428| ------ | ------ | ---- | --------------------- | 4429| callback | (event?: { callback: Function, fileSelector: object }) => void | 是 | 当触发文件选择器时需要执行的回调。 | 4430 4431 4432## onUrlLoadIntercept<sup>(deprecated)</sup> 4433 4434onUrlLoadIntercept(callback: (event?: { data:string | WebResourceRequest }) => boolean) 4435 4436当Web组件加载url之前触发该回调,用于判断是否阻止此次访问。 4437从API version 10开始不再维护,建议使用[onLoadIntercept<sup>10+</sup>](#onloadintercept10)代替。 4438 4439**系统能力:** SystemCapability.Web.Webview.Core 4440 4441**参数:** 4442 4443| 参数名 | 类型 | 必填 | 说明 | 4444| ------ | ------ | ---- | --------------------- | 4445| callback | (event?: { data:string \| [WebResourceRequest](./arkts-basic-components-web-WebResourceRequest.md) }) => boolean | 是 | url的相关信息。<br>返回值:boolean,true表示阻止此次加载,false表示允许此次加载。 | 4446 4447**示例:** 4448 4449 ```ts 4450 // xxx.ets 4451 import { webview } from '@kit.ArkWeb'; 4452 4453 @Entry 4454 @Component 4455 struct WebComponent { 4456 controller: webview.WebviewController = new webview.WebviewController(); 4457 4458 build() { 4459 Column() { 4460 Web({ src: 'www.example.com', controller: this.controller }) 4461 .onUrlLoadIntercept((event) => { 4462 if (event) { 4463 console.info('onUrlLoadIntercept ' + event.data.toString()); 4464 } 4465 return true 4466 }) 4467 } 4468 } 4469 } 4470 ``` 4471 4472## onPdfLoadEvent<sup>20+</sup> 4473 4474onPdfLoadEvent(callback: Callback\<OnPdfLoadEvent\>) 4475 4476通知用户PDF页面加载状态,包括成功或失败。 4477 4478**系统能力:** SystemCapability.Web.Webview.Core 4479 4480**参数:** 4481 4482| 参数名 | 类型 | 必填 | 说明 | 4483| ------- | --------------------------------- | ---- | --------- | 4484| callback | Callback\<[OnPdfLoadEvent](./arkts-basic-components-web-i.md#onpdfloadevent20)\> | 是 | 当PDF加载成功或失败时,会触发回调,通知用户PDF页面加载状态。 | 4485 4486**示例:** 4487 4488 ```ts 4489 // xxx.ets 4490 import { webview } from '@kit.ArkWeb'; 4491 4492 @Entry 4493 @Component 4494 struct WebComponent { 4495 controller: webview.WebviewController = new webview.WebviewController(); 4496 4497 build() { 4498 Column() { 4499 // 使用时需将'https://www.example.com/xxx.pdf'替换为真实可访问的地址 4500 Web({ src: 'https://www.example.com/xxx.pdf', controller: this.controller }) 4501 .onPdfLoadEvent((eventInfo: OnPdfLoadEvent) => { 4502 console.info(`Load event callback called. url: ${eventInfo.url}, result: ${eventInfo.result}.`) 4503 }) 4504 } 4505 } 4506 } 4507 ``` 4508 4509## onPdfScrollAtBottom<sup>20+</sup> 4510 4511onPdfScrollAtBottom(callback: Callback\<OnPdfScrollEvent\>) 4512 4513通知用户PDF页面已滚动到底。 4514 4515**系统能力:** SystemCapability.Web.Webview.Core 4516 4517**参数:** 4518 4519| 参数名 | 类型 | 必填 | 说明 | 4520| ------- | --------------------------------- | ---- | --------- | 4521| callback | Callback\<[OnPdfScrollEvent](./arkts-basic-components-web-i.md#onpdfscrollevent20)\> | 是 | 当PDF滚动到垂直方向底部时,会触发回调,通知用户PDF页面已滚动到底。 | 4522 4523**示例:** 4524 4525 ```ts 4526 // xxx.ets 4527 import { webview } from '@kit.ArkWeb'; 4528 4529 @Entry 4530 @Component 4531 struct WebComponent { 4532 controller: webview.WebviewController = new webview.WebviewController(); 4533 4534 build() { 4535 Column() { 4536 // 使用时需将'https://www.example.com/xxx.pdf'替换为真实可访问的地址 4537 Web({ src: 'https://www.example.com/xxx.pdf', controller: this.controller }) 4538 .onPdfScrollAtBottom((eventInfo: OnPdfScrollEvent) => { 4539 console.info(`Scroll at bottom callback called. url: ${eventInfo.url}.`) 4540 }) 4541 } 4542 } 4543 } 4544 ``` 4545