一、 需求场景
有时候,前端页面需要通过调用应用的函数获取数据,例如获取应用的版本信息、用户登录信息等应用数据。
二、实现方案
开发者使用Web组件将应用侧代码注册到前端页面中,注册完成之后,前端页面中使用注册的对象名称就可以调用应用侧的函数,实现在前端页面中调用应用侧方法。
注册应用侧代码有两种方式:
- 方式一:种在Web组件初始化调用,使用javaScriptProxy()接口。
- 方式二:在Web组件初始化完成后调用,使用registerJavaScriptProxy()接口,需要和deleteJavaScriptRegister接口配合使用,防止内存泄漏。
三、使用javaScriptProxy()接口使用示例
将TestClass类里的方法注册在前端页面中, 这些函数可以在前端页面触发运行。
3.1、示例代码
testArkWebH5CallNative.html
<!DOCTYPE html>
<html>
<meta charset="utf-8">
<style>
.btn {
width: 600px;
height: 100px;
font-size: 40px;
margin-top: 60px;
}
</style>
<body>
<strong style="font-size:40px;">调用原生方法</strong>
</br>
<button class="btn" id="callArkTSTestStr" type="button" onclick="callArkTSTestStr()">callArkTSTestStr方法</button>
</br>
<button class="btn" id="callArkTSTestArry" type="button" onclick="callArkTSTestArry()">callArkTSTestArray方法</button>
</br>
<button class="btn" id="callArkTStoString2" type="button" onclick="callArkTStoString2()">callArkTStoString2方法</button>
</br>
<button class="btn" id="callArkTSasyncTest" type="button" onclick="callArkTSasyncTest()">callArkTStoString2方法</button>
<p style="font-size:40px;" id="resultData"></p>
<script>
function callArkTSTestStr() {
let str = testObjName.testStr();
document.getElementById("resultData").innerHTML = str;
console.info('H5 callArkTSTestStr 调用原生 testStr 方法返回的数据:' + str);
}
function callArkTSTestArry() {
let arrayNum = testObjName.testArray();
console.info('H5 callArkTSTestArry 调用原生 testArray 方法返回的数据:' + arrayNum);
}
function callArkTStoString2() {
testObjName.toString2("这是来自H5数据");
console.info('H5 callArkTStoString2 调用原生 toString2 方法 传递的数据');
}
function callArkTSasyncTest() {
testObjName.asyncTest("这是来自H5调用 asyncTest 方法传递的数据");
console.info('H5 callArkTSasyncTest 调用原生 asyncTest 方法');
}
</script>
</body>
</html>
TestArkWebH5CallNative.ets
import { webview } from '@kit.ArkWeb'
import { promptAction } from '@kit.ArkUI'
import { BusinessError } from '@kit.BasicServicesKit'
class TestClass {
constructor() {
}
testStr(): string {
return "原生 testClass 里 test 方法返回的数据";
}
testArray(): Array<Number> {
return [1, 2, 3, 4, 5, 6];
}
toString(): void {
console.log('toString 方法 Web Component toString');
}
toString2(param: String): void {
console.log('toString2 方法 Web Component toString param:' + param);
}
asyncTest(data: string): void {
console.log("async data:" + data);
}
}
const JavaScriptProxy_NAME = "testObjName";
@Entry
@Component
struct TestArkWebH5CallNative {
@State message: string = '前端页面调用应用侧函数';
@State testClass: TestClass = new TestClass()
webviewController: webview.WebviewController = new webview.WebviewController()
aboutToAppear(): void {
try {
webview.WebviewController.setWebDebuggingAccess(true);
} catch (error) {
console.error(`aboutToAppear webview 配置Web开启调试模式出错了:ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
}
}
build() {
Column() {
Button('deleteJavaScriptRegister').fontColor(Color.Black).fontSize(20).onClick((_event) => {
try {
this.webviewController.deleteJavaScriptRegister(JavaScriptProxy_NAME);
} catch (error) {
console.error(`移除 testObjName 发生异常 ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
}
})
Web({ src: $rawfile('testArkWebH5CallNative.html'), controller: this.webviewController })// 将对象注入到web端
.javaScriptAccess(true)
.javaScriptProxy({
object: this.testClass,
name: JavaScriptProxy_NAME,
methodList: ["testStr", "testArray", "toString", "toString2"],
controller: this.webviewController,
// 可选参数
asyncMethodList: ["asyncTest"],
})
}
.height('100%')
.width('100%')
}
}
四、应用侧使用registerJavaScriptProxy()接口注册
将testClass2类里的方法注册在前端页面中, 这些函数可以在前端页面触发运行。
4.1 代码、
testArkWebH5CallNative2.html
<!DOCTYPE html>
<html>
<style>
.btn {
width: 600px;
height: 100px;
font-size: 40px;
margin-top: 60px;
}
</style>
<body>
<button class="btn" type="button" onclick="callArkTS()">Click Me!</button>
<p id="demo"></p>
<script>
function callArkTS() {
let str = testObjName.test();
document.getElementById("demo").innerHTML = str;
console.info('H5 callArkTS 调用原生 test 方法返回的数据:' + str);
}
</script>
</body>
</html>
TestArkWebH5CallNative2.ets
import { webview } from '@kit.ArkWeb'
import { BusinessError } from '@kit.BasicServicesKit';
class testClass2 {
constructor() {
}
test(): string {
return "原生 testClass2 类的 test 方法返回的数据 ";
}
toString(): void {
console.log('Web Component toString');
}
}
@Entry
@Component
struct TestArkWebH5CallNative2 {
@State message: string = 'Hello World';
@State webviewController: webview.WebviewController = new webview.WebviewController();
@State testObj: testClass2 = new testClass2();
private registerJavaScriptProxySucceed: boolean = false;
aboutToAppear(): void {
webview.WebviewController.setWebDebuggingAccess(true);
}
build() {
Column() {
Button("refresh")
.margin({ top: 20 })
.onClick(() => {
if (!this.registerJavaScriptProxySucceed) {
console.log("请先调用 registerJavaScriptProxy 方法")
return
}
try {
this.webviewController.refresh();
console.log("调用了 refresh 方法")
} catch (error) {
console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
}
})
Button('Register JavaScript To Window')
.margin({ top: 20 })
.onClick(() => {
try {
this.webviewController.registerJavaScriptProxy(this.testObj, "testObjName", ["test", "toString"],
// 可选参数, asyncMethodList
[]
);
this.registerJavaScriptProxySucceed = true;
console.log("调用了 registerJavaScriptProxy 方法");
} catch (error) {
console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
}
})
Button('deleteJavaScriptRegister')
.margin({ top: 20 })
.onClick(() => {
try {
this.webviewController.deleteJavaScriptRegister("testObjName");
console.log("调用了 deleteJavaScriptRegister 方法")
} catch (error) {
console.error(`ErrorCode: ${(error as BusinessError).code}, Message: ${(error as BusinessError).message}`);
}
})
Web({ src: $rawfile('testArkWebH5CallNative2.html'), controller: this.webviewController })
}
.height('100%')
.width('100%')
}
}