ArkWeb
Web 相關標準技術(HTML/CSS/JS),是業內支持性最廣泛的技術,可以在最廣泛的平臺下實現“一次編寫到處運行”;大部分對性能無需極致要求的應用頁面,都可以使用 Web 技術來實現。
鴻蒙 ArkWeb Kit(方舟 Web)提供了 Web 組件(也稱為 Webview 組件),本質就是 HTML/CSS/JS 解釋和渲染引擎,用于在應用程序中顯示 Web 頁面內容,為開發者提供頁面加載、頁面交互、頁面調試等能力。
- 頁面加載:Web 組件提供基礎的前端頁面加載的能力,包括加載網絡頁面、本地頁面、HTML 格式文本數據。
- 頁面交互:Web 組件提供豐富的頁面交互的方式,包括:設置前端頁面深色模式,新窗口中加載頁面,位置權限管理,Cookie 管理,應用側使用前端頁面 JavaScript 等能力。
- 頁面調試:Web 組件支持使用 Devtools 工具調試前端頁面
當前鴻蒙系統中的 Web 組件底層實現是開源的 Chromium 內核(Webkit + V8 組合);華為未來計劃完全自主實現該組件。
Web 組件生命周期
aboutToAppear
:可設置調試模式 / 跨域請求權限 / Cookie 等onControllerAttached
:推薦在此 loadUrl / 設置自定義用戶代理 / 注入 JS 對象等onLoadIntercept
:當 Web 組件加載 url 之前觸發該回調,用于判斷是否阻止此次訪問。默認 false 表允許加載onInterceptRequest
:當 Web 組件加載 url 之前觸發該回調,用于攔截 url 并返回響應數據onPageBegin
:網頁開始加載時觸發該回調onProgressChange
:網頁開始加載時觸發該回調onPageEnd
:網頁加載完成時觸發該回調,推薦在此回調中執行 runJavaScript()異步執行 JSonPageVisible
:當響應的主體開始加載,新頁面即將可見時觸發該回調;此時外鏈資源尚不可用onDisAppear
:組件卸載消失時觸發此回調
加載網絡頁面
開發者可以在 Web 組件創建時,指定默認加載的網絡頁面 。在默認頁面加載完成后,如果開發者需要變更此 Web 組件顯示的網絡頁面,可以通過調用 loadUrl()接口加載指定的網頁。
import { webview } from '@kit.ArkWeb'struct Page{controller = new webview.WebviewController( )build() {Column() {Button('loadUrl').onClick(() => {this.controller.loadUrl('www.10086.cn') //按鈕點擊后,加載第二個頁面})// 組件創建時,加載第一個頁面Web({ src: 'www.baidu.com', controller: this.controller})}}
}
涉及網絡資源獲取,需要配置 ohos.permission.INTERNET 權限
加載本地頁面
將本地頁面文件放在應用的 rawfile 目錄下,開發者可以在 Web 組件創建的時候指定默認加載的本地頁面 ,并且加載完成后可通過調用 loadUrl() 接口變更當前 Web 組件的頁面。
import { webview } from '@kit.ArkWeb'struct Page{controller = new webview.WebviewController( )build() {Column() {Button('loadPage').onClick(() => {this.controller.loadUrl( $rawfile("notfound.html") ) //加載第二個頁面})// 組件創建時,加載第一個頁面Web({ src: $rawfile("loading.html"), controller: this.controller})}}
}
加載 HTML 數據
Web 組件可以通過 loadData() 接口實現加載 HTML 格式的文本數據。當開發者不需要加載整個頁面,只需要顯示一些頁面片段時,可通過此功能來快速加載頁面。
import { webview } from '@kit.ArkWeb'
struct Page{controller = new webview.WebviewController()build() {Column() {Button('loadData').onClick(() => {this.controller.loadData( //按鈕點擊后,加載HTML片段"<html><body>Source:<pre>source</pre></body></html>","text/html","UTF-8" )})// 組件創建時,加載第一個頁面Web({ src: $rawfile("loading.html"), controller: this.controller })}}
}
應用側和 Web 側交互
數據通道
Web 側和應用側之間可以用 createWebMessagePorts() 創建兩個消息端口來實現兩端的通信
//應用側(ArkTS) —— 使用端口1發消息
ports: webview.WebMessagePort[ ] = [ ]this.ports = this.controller.createWebMessagePorts( ) //會創建兩個Port對象
this.controller.postMessage('init', [this.ports[0]], '*')this.ports[1].onMessageEvent((msg: webview.WebMessage) => {})
this.ports[1].postMessageEvent('msg')
//Web側(JS) —— 使用端口0發消息
let port = null;
window.addEventListener("message", (e) => {port = e.ports[0];port.onmessage = (m) => {};
});
bt.onclick = () => {port.postMessage("This is Client - " + Date.now());
};
應用側調 Web 側函數
應用側可以通過 runJavaScript( ) 方法調用前端頁面的 JavaScript 相關函數:
前端頁面聲明 JS 函數:
<script>function startLottery() {//開始}
</script>
應用側調用前端頁面函數:
Button("運行JS代碼").onClick(() => {this.controller.runJavaScript("startLottery( )");//需要傳參的話也可以在上述函數調用過程中傳遞,返回值可以在Promise中讀取
});
Web 側調應用側函數
開發者使用 Web 組件將應用側代碼 注冊 到前端頁面中,注冊完成之后,前端頁面中使用注冊的對象名稱就可以調用應用側的函數,實現在前端頁面中調用應用側方法。
應用側注冊對象和方法(代理方法)給前端頁面:
Web({src: $rawfile("page.html"),controller: this.controller,
}).javaScriptProxy({//給Web側注冊一個代理對象object: this, //被代理的對象name: "appObj", //代理人在Web端的名稱methodList: ["back"], //被代理的對象中哪些方法要暴露給Web側controller: this.controller,
});
前端頁面調用應用側注冊來的對象和方法:
<script>btn.onclick = () => {appObj.back(); //需要傳參的話可以在形參處傳遞,返回值可以在Promise中讀取};
</script>