试试激动人心的 WebView2
WebView2 实在诱人,最新的 Edge(Chromium) 性能强悍,而且所有使用 WebView2 的应用可以共用一个运行时,Windows 11 已经自带 WebView2 ,就连 Office 也会自动部署 WebView2 ,目前 WebView2 已经被部署到 2亿台电脑,并且还在继续增加 …… 未来是属于 WebView2 的。即使目标电脑没有安装 WebView2 ,在 aardio 中调用 WebView2 以前也会自动检测并安装 —— WebView2 的下载安装速度极快,所以对用户体验基本没有影响,重要的是 WebView2 仍然支持老旧的、即将被淘汰的 Windows 7 —— 拥有良好的兼容性。
令人惊讶的是 WebView2 居然支持 COM 对象,这就非常舒服了,我们知道 aardio 先天对 COM 友好,所有 aardio 对象都可以自动转换为 COM 对象,因此我们在 WebView2 中与 aardio 交互就非常方便,可能比其他浏览器组件都要方便。
要尝试 WebView2 非常简单,在工程向导里可以创建 WebView2 工程,也可以在新建窗口里简单的创建 WebView2 单窗口示例。
今天我们一起小试一下 WebView2 ,写一个小工具。
我们需要做到以下几点:
1、在 aardio 中轻松愉快地嵌入 WebView2,生成极小的 EXE 文件。
2、有了性能强悍的 WebView2,我们还想把前端好用的东西搬上桌品尝,例如 React hooks,Ant Design, Babel 等等,不会前端开发环境没有关系,今天我们简单一点,直接在网页中引入 Babel。不用担心,因为 WebView2 实在太快了,即使在网页中直接调用 Babel 编译,速度也是快如闪电,写这么个简单的页面完全没问题。
3、我们需要在网页中调用 aardio 本地函数,并且在网页中通过 aardio 访问电脑硬件接口,如果只是跑个网页那就太没意思了。我们要做浏览器做不了的事情。
我们之前刚刚写了一个访问路由器端口映射数据的库 sys.upnp.nat ,就先拿这个来练手。今天要说的这个示例我已经放到了 aardio 自带的范例中,可以在以下位置打开:
运行后的效果:
关键代码如下:
import win.ui;
/*DSG{{*/
var winform = win.form(text='UPnP 端口映射查看工具')
/*}}*/
import web.view;
var wb = web.view(winform);
import sys.upnp.nat;
var natUpnp = sys.upnp.nat();
wb.external = {
getMappingCollection = function(){
return web.json.stringifyArray(natUpnp.getTable());
};
deleteItem = function(externalPort,protocol){
return natUpnp.remove(externalPort,protocol)
};
}
wb.html = /**
省略 HTML 代码
**/
winform.show();
win.loopMessage();
上面 wb.external 导出了 JavaScript 可以调用的函数。因为 external 在返回表对象、数组时会转换为 COM 对象,而我们在 React 加载的数据需要 JSON ,所以上面我们通过 web.json.stringifyArray(natUpnp.getTable()) 返回一个 JSON 数组。
在网页中调用 aardio 函数有 2 个重要的规则:
1、所有在 aardio 中导出到 JavaScript 的函数都是异步函数,也就是 Promise 。
2、在网页中调用 aardio 函数,总是在界面线程中调用,这就避免了不必要的跨线程同步,非常方便。
再看一下网页中调用 aardio 函数的关键代码:
<script type='text/babel'> const { useState,useEffect } = React; const App = () => { const [data,setData] = useState([]); useEffect( async ()=> { var ds = await aardio.getMappingCollection(); setData(JSON.parse(ds)); },[] ) //其他代码省略 }; ReactDOM.render(<App />, document.querySelector('#app')); </script>
注意 aardio.getMappingCollection() 返回一个 Promise ,而 await aardio.getMappingCollection() 才是返回 aardio 函数真正的返回值。