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>