一、ArkWeb 與原生交互方式
(一)原生向 Web 注入 JavaScript 代碼
1. 原理
在原生應(yīng)用中,通過 ArkWeb 提供的 API 向 Web 頁面注入 JavaScript 代碼,從而實現(xiàn)對 Web 頁面的控制和數(shù)據(jù)傳遞。
2. 代碼示例
import { Web, WebRef, WebPageLoadEvent } from '@ohos.web.webview';
@Entry
@Component
struct NativeToWebExample {
? private webRef: WebRef | null = null;
? build() {
? ? Column({ space: 50 }) {
? ? ? Web({
? ? ? ? src: 'https://example.com',
? ? ? ? onPageLoadFinish: (event: WebPageLoadEvent) => {
? ? ? ? ? if (this.webRef) {
? ? ? ? ? ? // 注入JavaScript代碼
? ? ? ? ? ? this.webRef.executeJs('document.getElementById("demo").innerHTML = "Hello from Native";');
? ? ? ? ? }
? ? ? ? }
? ? ? })
? ? ? .width('100%')
? ? ? .height('80%')
? ? ? .ref((ref) => {
? ? ? ? this.webRef = ref;
? ? ? })
? ? ? Button('Send Message to Web')
? ? ? ? .onClick(() => {
? ? ? ? ? if (this.webRef) {
? ? ? ? ? ? this.webRef.executeJs('alert("Message from native app!");');
? ? ? ? ? }
? ? ? ? })
? ? }
? }
}
(二)Web 向原生發(fā)送消息
1. 原理
在 Web 頁面中,使用window.postMessage方法向原生應(yīng)用發(fā)送消息,原生應(yīng)用通過監(jiān)聽onMessageReceived事件接收消息。
2. 代碼示例
Web 頁面代碼(HTML + JavaScript)
<!DOCTYPE html>
<html>
<head>
? <meta charset="UTF-8">
? <title>Web to Native</title>
</head>
<body>
? <button onclick="sendMessageToNative()">Send Message to Native</button>
? <script>
? ? function sendMessageToNative() {
? ? ? window.postMessage('Hello from Web', '*');
? ? }
? </script>
</body>
</html>
原生應(yīng)用代碼(ArkTS)
import { Web, WebMessageEvent } from '@ohos.web.webview';
@Entry
@Component
struct WebToNativeExample {
? build() {
? ? Web({
? ? ? src: 'file:///data/storage/el2/base/haps/entry/files/webpage.html',
? ? ? onMessageReceived: (event: WebMessageEvent) => {
? ? ? ? console.log('Received message from web: ' + event.data);
? ? ? }
? ? })
? ? .width('100%')
? ? .height('100%')
? }
}
(三)原生與 Web 雙向數(shù)據(jù)綁定
1. 原理
結(jié)合上述兩種方式,實現(xiàn)原生與 Web 之間的數(shù)據(jù)雙向同步,當(dāng)原生數(shù)據(jù)變化時更新 Web 頁面,當(dāng) Web 頁面數(shù)據(jù)變化時更新原生數(shù)據(jù)。
2. 代碼示例
import { Web, WebRef, WebPageLoadEvent, WebMessageEvent } from '@ohos.web.webview';
@Entry
@Component
struct BiDirectionalBindingExample {
? private webRef: WebRef | null = null;
? private nativeData: string = 'Initial Value';
? build() {
? ? Column({ space: 50 }) {
? ? ? Web({
? ? ? ? src: 'https://example.com',
? ? ? ? onPageLoadFinish: (event: WebPageLoadEvent) => {
? ? ? ? ? if (this.webRef) {
? ? ? ? ? ? // 初始化Web頁面數(shù)據(jù)
? ? ? ? ? ? this.webRef.executeJs(`document.getElementById("data-display").innerHTML = "${this.nativeData}";`);
? ? ? ? ? }
? ? ? ? },
? ? ? ? onMessageReceived: (event: WebMessageEvent) => {
? ? ? ? ? // 更新原生數(shù)據(jù)
? ? ? ? ? this.nativeData = event.data;
? ? ? ? ? console.log('Updated native data: ' + this.nativeData);
? ? ? ? }
? ? ? })
? ? ? .width('100%')
? ? ? .height('80%')
? ? ? .ref((ref) => {
? ? ? ? this.webRef = ref;
? ? ? })
? ? ? Button('Update Web Data')
? ? ? ? .onClick(() => {
? ? ? ? ? this.nativeData = 'New Value';
? ? ? ? ? if (this.webRef) {
? ? ? ? ? ? // 更新Web頁面數(shù)據(jù)
? ? ? ? ? ? this.webRef.executeJs(`document.getElementById("data-display").innerHTML = "${this.nativeData}";`);
? ? ? ? ? }
? ? ? ? })
? ? }
? }
}
二、注意事項
(一)安全性方面
1、輸入驗證
原生向 Web 注入 JavaScript 代碼時,要對注入的代碼進(jìn)行嚴(yán)格的輸入驗證,防止惡意代碼注入。例如,避免直接將用戶輸入作為 JavaScript 代碼注入,應(yīng)進(jìn)行轉(zhuǎn)義和過濾。
Web 向原生發(fā)送消息時,原生應(yīng)用要對接收的消息進(jìn)行合法性檢查,防止接收惡意消息。
2、跨域安全
在使用window.postMessage時,要明確指定目標(biāo)源(targetOrigin),避免消息被惡意攔截或篡改。例如,在 Web 頁面中使用window.postMessage('message', 'https://example.com'),確保消息只能發(fā)送到指定的源。
(二)性能方面
1、減少頻繁交互
頻繁的原生與 Web 交互會影響應(yīng)用的性能,盡量減少不必要的交互。例如,避免在短時間內(nèi)多次向 Web 注入大量 JavaScript 代碼或頻繁發(fā)送消息。
2、異步處理
對于耗時的交互操作,如網(wǎng)絡(luò)請求、大量數(shù)據(jù)處理等,要采用異步處理方式,避免阻塞主線程。例如,在原生應(yīng)用中使用Promise或async/await處理耗時操作。
(三)兼容性方面
1、瀏覽器內(nèi)核差異
HarmonyOS 中的 ArkWeb 可能采用不同的瀏覽器內(nèi)核,要確保 Web 頁面在各種內(nèi)核下都能正常與原生應(yīng)用交互??梢赃M(jìn)行多內(nèi)核測試,針對不同內(nèi)核進(jìn)行必要的兼容性處理。
2、版本兼容性
要注意 ArkWeb API 的版本兼容性,不同版本的 HarmonyOS 可能支持不同的 API。在開發(fā)過程中,要根據(jù)目標(biāo)設(shè)備的系統(tǒng)版本選擇合適的 API 進(jìn)行開發(fā)。
(四)內(nèi)存管理方面
1、及時釋放資源
在 Web 頁面不再使用時,要及時釋放相關(guān)資源,避免內(nèi)存泄漏。例如,在組件銷毀時調(diào)用Web組件的清理方法。
@Component
struct MemoryManagementExample {
? private webRef: WebRef | null = null;
? aboutToDisappear() {
? ? if (this.webRef) {
? ? ? this.webRef.destroy();
? ? }
? }
? build() {
? ? Web({
? ? ? src: 'https://example.com'
? ? })
? ? .width('100%')
? ? .height('100%')
? ? .ref((ref) => {
? ? ? this.webRef = ref;
? ? })
? }
}
2、數(shù)據(jù)緩存管理
對于交互過程中產(chǎn)生的數(shù)據(jù)緩存,要進(jìn)行合理的管理,避免占用過多內(nèi)存。例如,定期清理不再使用的緩存數(shù)據(jù)。