1# 前端页面调用应用侧函数
2
3
4开发者使用Web组件将应用侧代码注册到前端页面中,注册完成之后,前端页面中使用注册的对象名称就可以调用应用侧的函数,实现在前端页面中调用应用侧方法。
5
6
7注册应用侧代码有两种方式,一种在Web组件初始化调用,使用[javaScriptProxy()](../reference/apis-arkweb/ts-basic-components-web.md#javascriptproxy)接口。另外一种在Web组件初始化完成后调用,使用[registerJavaScriptProxy()](../reference/apis-arkweb/js-apis-webview.md#registerjavascriptproxy)接口, 需要和[deleteJavaScriptRegister](../reference/apis-arkweb/js-apis-webview.md#deletejavascriptregister)接口配合使用,防止内存泄漏。
8
9
10在下面的示例中,将test()方法注册在前端页面中, 该函数可以在前端页面触发运行。
11
12
13- [javaScriptProxy()](../reference/apis-arkweb/ts-basic-components-web.md#javascriptproxy)接口使用示例如下。
14
15  ```ts
16  // xxx.ets
17  import { webview } from '@kit.ArkWeb';
18  import { BusinessError } from '@kit.BasicServicesKit';
19
20  class testClass {
21    constructor() {
22    }
23
24    test(): string {
25      return 'ArkTS Hello World!';
26    }
27  }
28
29  @Entry
30  @Component
31  struct WebComponent {
32    webviewController: webview.WebviewController = new webview.WebviewController();
33    // 声明需要注册的对象
34    @State testObj: testClass = new testClass();
35
36    build() {
37      Column() {
38        Button('deleteJavaScriptRegister')
39          .onClick(() => {
40            try {
41              this.webviewController.deleteJavaScriptRegister("testObjName");
42            } catch (error) {
43              console.error(`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}`);
44            }
45          })
46        // Web组件加载本地index.html页面
47        Web({ src: $rawfile('index.html'), controller: this.webviewController})
48          // 将对象注入到web端
49          .javaScriptProxy({
50            object: this.testObj,
51            name: "testObjName",
52            methodList: ["test"],
53            controller: this.webviewController,
54            // 可选参数
55            asyncMethodList: [],
56            permission: '{"javascriptProxyPermission":{"urlPermissionList":[{"scheme":"resource","host":"rawfile","port":"","path":""},' +
57                        '{"scheme":"e","host":"f","port":"g","path":"h"}],"methodList":[{"methodName":"test","urlPermissionList":' +
58                        '[{"scheme":"https","host":"xxx.com","port":"","path":""},{"scheme":"resource","host":"rawfile","port":"","path":""}]},' +
59                        '{"methodName":"test11","urlPermissionList":[{"scheme":"q","host":"r","port":"","path":"t"},' +
60                        '{"scheme":"u","host":"v","port":"","path":""}]}]}}'
61          })
62      }
63    }
64  }
65  ```
66
67
68- 应用侧使用[registerJavaScriptProxy()](../reference/apis-arkweb/js-apis-webview.md#registerjavascriptproxy)接口注册。
69
70  ```ts
71  // xxx.ets
72  import { webview } from '@kit.ArkWeb';
73  import { BusinessError } from '@kit.BasicServicesKit';
74
75  class testClass {
76    constructor() {
77    }
78
79    test(): string {
80      return "ArkUI Web Component";
81    }
82
83    toString(): void {
84      console.log('Web Component toString');
85    }
86  }
87
88  @Entry
89  @Component
90  struct Index {
91    webviewController: webview.WebviewController = new webview.WebviewController();
92    @State testObj: testClass = new testClass();
93
94    build() {
95      Column() {
96        Button('refresh')
97          .onClick(() => {
98            try {
99              this.webviewController.refresh();
100            } catch (error) {
101              console.error(`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}`);
102            }
103          })
104        Button('Register JavaScript To Window')
105          .onClick(() => {
106            try {
107              this.webviewController.registerJavaScriptProxy(this.testObj, "testObjName", ["test", "toString"],
108                      // 可选参数, asyncMethodList
109                      [],
110                      // 可选参数, permission
111                      '{"javascriptProxyPermission":{"urlPermissionList":[{"scheme":"resource","host":"rawfile","port":"","path":""},' +
112                      '{"scheme":"e","host":"f","port":"g","path":"h"}],"methodList":[{"methodName":"test","urlPermissionList":' +
113                      '[{"scheme":"https","host":"xxx.com","port":"","path":""},{"scheme":"resource","host":"rawfile","port":"","path":""}]},' +
114                      '{"methodName":"test11","urlPermissionList":[{"scheme":"q","host":"r","port":"","path":"t"},' +
115                      '{"scheme":"u","host":"v","port":"","path":""}]}]}}'
116              );
117            } catch (error) {
118              console.error(`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}`);
119            }
120          })
121        Button('deleteJavaScriptRegister')
122          .onClick(() => {
123            try {
124              this.webviewController.deleteJavaScriptRegister("testObjName");
125            } catch (error) {
126              console.error(`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}`);
127            }
128          })
129        Web({ src: $rawfile('index.html'), controller: this.webviewController })
130      }
131    }
132  }
133  ```
134
135  > **说明:**
136  >
137  > - 使用[registerJavaScriptProxy()](../reference/apis-arkweb/js-apis-webview.md#registerjavascriptproxy)接口注册方法时,注册后需调用[refresh()](../reference/apis-arkweb/js-apis-webview.md#refresh)接口生效。
138
139- 可选参数permission是一个json字符串,示例如下:
140  ```json
141  {
142    "javascriptProxyPermission": {
143      "urlPermissionList": [       // Object级权限,如果匹配,所有Method都授权
144        {
145          "scheme": "resource",    // 精确匹配,不能为空
146          "host": "rawfile",       // 精确匹配,不能为空
147          "port": "",              // 精确匹配,为空不检查
148          "path": ""               // 前缀匹配,为空不检查
149        },
150        {
151          "scheme": "https",       // 精确匹配,不能为空
152          "host": "xxx.com",       // 精确匹配,不能为空
153          "port": "8080",          // 精确匹配,为空不检查
154          "path": "a/b/c"          // 前缀匹配,为空不检查
155        }
156      ],
157      "methodList": [
158        {
159          "methodName": "test",
160          "urlPermissionList": [   // Method级权限
161            {
162              "scheme": "https",   // 精确匹配,不能为空
163              "host": "xxx.com",   // 精确匹配,不能为空
164              "port": "",          // 精确匹配,为空不检查
165              "path": ""           // 前缀匹配,为空不检查
166            },
167            {
168              "scheme": "resource",// 精确匹配,不能为空
169              "host": "rawfile",   // 精确匹配,不能为空
170              "port": "",          // 精确匹配,为空不检查
171              "path": ""           // 前缀匹配,为空不检查
172            }
173          ]
174        },
175        {
176          "methodName": "test11",
177          "urlPermissionList": [   // Method级权限
178            {
179              "scheme": "q",       // 精确匹配,不能为空
180              "host": "r",         // 精确匹配,不能为空
181              "port": "",          // 精确匹配,为空不检查
182              "path": "t"          // 前缀匹配,为空不检查
183            },
184            {
185              "scheme": "u",       // 精确匹配,不能为空
186              "host": "v",         // 精确匹配,不能为空
187              "port": "",          // 精确匹配,为空不检查
188              "path": ""           // 前缀匹配,为空不检查
189            }
190          ]
191        }
192      ]
193    }
194  }
195  ```
196
197- index.html前端页面触发应用侧代码。
198
199  ```html
200  <!-- index.html -->
201  <!DOCTYPE html>
202  <html>
203  <body>
204  <button type="button" onclick="callArkTS()">Click Me!</button>
205  <p id="demo"></p>
206  <script>
207      function callArkTS() {
208          let str = testObjName.test();
209          document.getElementById("demo").innerHTML = str;
210          console.info('ArkTS Hello World! :' + str);
211      }
212  </script>
213  </body>
214  </html>
215  ```
216## 复杂类型使用方法
217- 应用侧和前端页面之间传递Array。
218  ```ts
219  // xxx.ets
220  import { webview } from '@kit.ArkWeb';
221  import { BusinessError } from '@kit.BasicServicesKit';
222
223  class testClass {
224    constructor() {
225    }
226
227    test(): Array<Number> {
228      return [1, 2, 3, 4]
229    }
230
231    toString(param: String): void {
232      console.log('Web Component toString' + param);
233    }
234  }
235
236  @Entry
237  @Component
238  struct Index {
239    webviewController: webview.WebviewController = new webview.WebviewController();
240    @State testObj: testClass = new testClass();
241
242    build() {
243      Column() {
244        Button('refresh')
245          .onClick(() => {
246            try {
247              this.webviewController.refresh();
248            } catch (error) {
249              console.error(`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}`);
250            }
251          })
252        Button('Register JavaScript To Window')
253          .onClick(() => {
254            try {
255              this.webviewController.registerJavaScriptProxy(this.testObj, "testObjName", ["test", "toString"]);
256            } catch (error) {
257              console.error(`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}`);
258            }
259          })
260        Button('deleteJavaScriptRegister')
261          .onClick(() => {
262            try {
263              this.webviewController.deleteJavaScriptRegister("testObjName");
264            } catch (error) {
265              console.error(`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}`);
266            }
267          })
268        Web({ src: $rawfile('index.html'), controller: this.webviewController })
269      }
270    }
271  }
272  ```
273
274  ```html
275  <!-- index.html -->
276  <!DOCTYPE html>
277  <html>
278  <body>
279  <button type="button" onclick="callArkTS()">Click Me!</button>
280  <p id="demo"></p>
281  <script>
282      function callArkTS() {
283          testObjName.toString(testObjName.test());
284      }
285  </script>
286  </body>
287  </html>
288  ```
289- 应用侧和前端页面之间传递基础类型,非Function等复杂类型。
290  ```ts
291  // xxx.ets
292  import { webview } from '@kit.ArkWeb';
293  import { BusinessError } from '@kit.BasicServicesKit';
294
295  class student {
296    name: string = '';
297    age: string = '';
298  }
299
300  class testClass {
301    constructor() {
302    }
303
304    // 传递的基础类型name:"jeck", age:"12"。
305    test(): student {
306      let st: student = { name: "jeck", age: "12" };
307      return st;
308    }
309
310    toString(param: ESObject): void {
311      console.log('Web Component toString' + param["name"]);
312    }
313  }
314
315  @Entry
316  @Component
317  struct Index {
318    webviewController: webview.WebviewController = new webview.WebviewController();
319    @State testObj: testClass = new testClass();
320
321    build() {
322      Column() {
323        Button('refresh')
324          .onClick(() => {
325            try {
326              this.webviewController.refresh();
327            } catch (error) {
328              console.error(`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}`);
329            }
330          })
331        Button('Register JavaScript To Window')
332          .onClick(() => {
333            try {
334              this.webviewController.registerJavaScriptProxy(this.testObj, "testObjName", ["test", "toString"]);
335            } catch (error) {
336              console.error(`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}`);
337            }
338          })
339        Button('deleteJavaScriptRegister')
340          .onClick(() => {
341            try {
342              this.webviewController.deleteJavaScriptRegister("testObjName");
343            } catch (error) {
344              console.error(`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}`);
345            }
346          })
347        Web({ src: $rawfile('index.html'), controller: this.webviewController })
348      }
349    }
350  }
351  ```
352
353  ```html
354  <!-- index.html -->
355  <!DOCTYPE html>
356  <html>
357  <body>
358  <button type="button" onclick="callArkTS()">Click Me!</button>
359  <p id="demo"></p>
360  <script>
361      function callArkTS() {
362          testObjName.toString(testObjName.test());
363      }
364  </script>
365  </body>
366  </html>
367  ```
368
369- 应用侧调用前端页面的Callback。
370  ```ts
371  // xxx.ets
372  import { webview } from '@kit.ArkWeb';
373  import { BusinessError } from '@kit.BasicServicesKit';
374
375  class testClass {
376    constructor() {
377    }
378
379    test(param: Function): void {
380      param("call callback");
381    }
382
383    toString(param: String): void {
384      console.log('Web Component toString' + param);
385    }
386  }
387
388  @Entry
389  @Component
390  struct Index {
391    webviewController: webview.WebviewController = new webview.WebviewController();
392    @State testObj: testClass = new testClass();
393
394    build() {
395      Column() {
396        Button('refresh')
397          .onClick(() => {
398            try {
399              this.webviewController.refresh();
400            } catch (error) {
401              console.error(`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}`);
402            }
403          })
404        Button('Register JavaScript To Window')
405          .onClick(() => {
406            try {
407              this.webviewController.registerJavaScriptProxy(this.testObj, "testObjName", ["test", "toString"]);
408            } catch (error) {
409              console.error(`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}`);
410            }
411          })
412        Button('deleteJavaScriptRegister')
413          .onClick(() => {
414            try {
415              this.webviewController.deleteJavaScriptRegister("testObjName");
416            } catch (error) {
417              console.error(`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}`);
418            }
419          })
420        Web({ src: $rawfile('index.html'), controller: this.webviewController })
421      }
422    }
423  }
424  ```
425
426  ```html
427  <!-- index.html -->
428  <!DOCTYPE html>
429  <html>
430  <body>
431  <button type="button" onclick="callArkTS()">Click Me!</button>
432  <p id="demo"></p>
433  <script>
434      function callArkTS() {
435          testObjName.test(function(param){testObjName.toString(param)});
436      }
437  </script>
438  </body>
439  </html>
440  ```
441
442- 应用侧调用前端页面Object里的Function。
443  ```ts
444  // xxx.ets
445  import { webview } from '@kit.ArkWeb';
446  import { BusinessError } from '@kit.BasicServicesKit';
447
448  class testClass {
449    constructor() {
450    }
451
452    test(param: ESObject): void {
453      param.hello("call obj func");
454    }
455
456    toString(param: String): void {
457      console.log('Web Component toString' + param);
458    }
459  }
460
461  @Entry
462  @Component
463  struct Index {
464    webviewController: webview.WebviewController = new webview.WebviewController();
465    @State testObj: testClass = new testClass();
466
467    build() {
468      Column() {
469        Button('refresh')
470          .onClick(() => {
471            try {
472              this.webviewController.refresh();
473            } catch (error) {
474              console.error(`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}`);
475            }
476          })
477        Button('Register JavaScript To Window')
478          .onClick(() => {
479            try {
480              this.webviewController.registerJavaScriptProxy(this.testObj, "testObjName", ["test", "toString"]);
481            } catch (error) {
482              console.error(`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}`);
483            }
484          })
485        Button('deleteJavaScriptRegister')
486          .onClick(() => {
487            try {
488              this.webviewController.deleteJavaScriptRegister("testObjName");
489            } catch (error) {
490              console.error(`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}`);
491            }
492          })
493        Web({ src: $rawfile('index.html'), controller: this.webviewController })
494      }
495    }
496  }
497  ```
498
499  ```html
500  <!-- index.html -->
501  <!DOCTYPE html>
502  <html>
503  <body>
504  <button type="button" onclick="callArkTS()">Click Me!</button>
505  <p id="demo"></p>
506  <script>
507      // 写法1
508      class Student {
509          constructor(nameList) {
510              this.methodNameListForJsProxy = nameList;
511          }
512
513          hello(param) {
514              testObjName.toString(param)
515          }
516      }
517      var st = new Student(["hello"])
518
519      // 写法2
520      //创建一个构造器,构造函数首字母大写
521      function Obj1(){
522          this.methodNameListForJsProxy=["hello"];
523          this.hello=function(param){
524              testObjName.toString(param)
525          };
526      }
527      //利用构造器,通过new关键字生成对象
528      var st1 = new Obj1();
529
530      function callArkTS() {
531          testObjName.test(st);
532          testObjName.test(st1);
533      }
534  </script>
535  </body>
536  </html>
537  ```
538
539- 前端页面调用应用侧Object里的Function。
540  ```ts
541  // xxx.ets
542  import { webview } from '@kit.ArkWeb';
543  import { BusinessError } from '@kit.BasicServicesKit';
544
545  class ObjOther {
546    methodNameListForJsProxy: string[]
547
548    constructor(list: string[]) {
549      this.methodNameListForJsProxy = list
550    }
551
552    testOther(json: string): void {
553      console.info(json)
554    }
555  }
556
557  class testClass {
558    ObjReturn: ObjOther
559
560    constructor() {
561      this.ObjReturn = new ObjOther(["testOther"]);
562    }
563
564    test(): ESObject {
565      return this.ObjReturn
566    }
567
568    toString(param: string): void {
569      console.log('Web Component toString' + param);
570    }
571  }
572
573  @Entry
574  @Component
575  struct Index {
576    webviewController: webview.WebviewController = new webview.WebviewController();
577    @State testObj: testClass = new testClass();
578
579    build() {
580      Column() {
581        Button('refresh')
582          .onClick(() => {
583            try {
584              this.webviewController.refresh();
585            } catch (error) {
586              console.error(`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}`);
587            }
588          })
589        Button('Register JavaScript To Window')
590          .onClick(() => {
591            try {
592              this.webviewController.registerJavaScriptProxy(this.testObj, "testObjName", ["test", "toString"]);
593            } catch (error) {
594              console.error(`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}`);
595            }
596          })
597        Button('deleteJavaScriptRegister')
598          .onClick(() => {
599            try {
600              this.webviewController.deleteJavaScriptRegister("testObjName");
601            } catch (error) {
602              console.error(`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}`);
603            }
604          })
605        Web({ src: $rawfile('index.html'), controller: this.webviewController })
606      }
607    }
608  }
609  ```
610
611  ```html
612  <!-- index.html -->
613  <!DOCTYPE html>
614  <html>
615  <body>
616  <button type="button" onclick="callArkTS()">Click Me!</button>
617  <p id="demo"></p>
618  <script>
619      function callArkTS() {
620        testObjName.test().testOther("call other object func");
621      }
622  </script>
623  </body>
624  </html>
625  ```
626
627- Promise场景。<br>
628  第一种使用方法,在应用侧new Promise。
629  ```ts
630  // xxx.ets
631  import { webview } from '@kit.ArkWeb';
632  import { BusinessError } from '@kit.BasicServicesKit';
633
634  class testClass {
635    constructor() {
636    }
637
638    test(): Promise<string> {
639      let p: Promise<string> = new Promise((resolve, reject) => {
640        setTimeout(() => {
641          console.log('执行完成');
642          reject('fail');
643        }, 10000);
644      });
645      return p;
646    }
647
648    toString(param: String): void {
649      console.log(" " + param);
650    }
651  }
652
653  @Entry
654  @Component
655  struct Index {
656    webviewController: webview.WebviewController = new webview.WebviewController();
657    @State testObj: testClass = new testClass();
658
659    build() {
660      Column() {
661        Button('refresh')
662          .onClick(() => {
663            try {
664              this.webviewController.refresh();
665            } catch (error) {
666              console.error(`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}`);
667            }
668          })
669        Button('Register JavaScript To Window')
670          .onClick(() => {
671            try {
672              this.webviewController.registerJavaScriptProxy(this.testObj, "testObjName", ["test", "toString"]);
673            } catch (error) {
674              console.error(`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}`);
675            }
676          })
677        Button('deleteJavaScriptRegister')
678          .onClick(() => {
679            try {
680              this.webviewController.deleteJavaScriptRegister("testObjName");
681            } catch (error) {
682              console.error(`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}`);
683            }
684          })
685        Web({ src: $rawfile('index.html'), controller: this.webviewController })
686      }
687    }
688  }
689  ```
690
691  ```html
692  <!-- index.html -->
693  <!DOCTYPE html>
694  <html>
695  <body>
696  <button type="button" onclick="callArkTS()">Click Me!</button>
697  <p id="demo"></p>
698  <script>
699      function callArkTS() {
700        testObjName.test().then((param)=>{testObjName.toString(param)}).catch((param)=>{testObjName.toString(param)})
701      }
702  </script>
703  </body>
704  </html>
705  ```
706  第二种使用方法,在前端页面new Promise。
707  ```ts
708  // xxx.ets
709  import { webview } from '@kit.ArkWeb';
710  import { BusinessError } from '@kit.BasicServicesKit';
711
712  class testClass {
713    constructor() {
714    }
715
716    test(param:Function): void {
717      setTimeout( () => { param("suc") }, 10000)
718    }
719
720    toString(param:String): void {
721      console.log(" " + param);
722    }
723  }
724
725  @Entry
726  @Component
727  struct Index {
728    webviewController: webview.WebviewController = new webview.WebviewController();
729    @State testObj: testClass = new testClass();
730
731    build() {
732      Column() {
733        Button('refresh')
734          .onClick(() => {
735            try {
736              this.webviewController.refresh();
737            } catch (error) {
738              console.error(`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}`);
739            }
740          })
741        Button('Register JavaScript To Window')
742          .onClick(() => {
743            try {
744              this.webviewController.registerJavaScriptProxy(this.testObj, "testObjName", ["test", "toString"]);
745            } catch (error) {
746              console.error(`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}`);
747            }
748          })
749        Button('deleteJavaScriptRegister')
750          .onClick(() => {
751            try {
752              this.webviewController.deleteJavaScriptRegister("testObjName");
753            } catch (error) {
754              console.error(`ErrorCode: ${(error as BusinessError).code},  Message: ${(error as BusinessError).message}`);
755            }
756          })
757        Web({ src: $rawfile('index.html'), controller: this.webviewController })
758      }
759    }
760  }
761  ```
762
763  ```html
764  <!-- index.html -->
765  <!DOCTYPE html>
766  <html>
767  <body>
768  <button type="button" onclick="callArkTS()">Click Me!</button>
769  <p id="demo"></p>
770  <script>
771      function callArkTS() {
772        let funpromise
773        var p = new Promise(function(resolve, reject){funpromise=(param)=>{resolve(param)}})
774        testObjName.test(funpromise)
775        p.then((param)=>{testObjName.toString(param)})
776      }
777  </script>
778  </body>
779  </html>
780  ```
781