Electron 不錯,但也不是完美的,
Electron 帶來了很多優秀的桌面軟體,但并不一定總是適合我們的需求,
多個選擇總是好事!
? 我使用 Electron 遇到的一些麻煩
1、Electron 太大了!
2、每一個 Electron 寫的軟體都要重復地帶一個 Electron …… 升級與分發都不方便,
3、Electron 不方便嵌入其他視窗界面,與其他語言、技術融合不易,
4、并不是所有桌面軟體都需要 Electron 的跨平臺特性,macOS , Linux 的桌面系統市場份額小于被遺忘的 Windows 8 ,如果軟體只是在 Windows 平臺運行,并且需要大量與專用系統 API 互動,跨平臺反而是不必要的負擔,
5、我曾經在 aardio 中封裝了一個 electron 擴展庫,然后我在寫這個擴展庫的時候,當時看到的還是 remote 真香 …… 然后我為這個擴展庫寫了個很大的 JS 檔案就用到了 remote,可是等我寫完沒多久, 就看到 remote 被 Electron 拋棄了,remote 會慢一萬倍 ,各種缺陷 ……
? WebView2 的優勢
1、WebView2 基于性能強悍的 Edge(Chromium) 內核,
2、呼叫 WebView2 生成的軟體體積很小,所有基于 WebView2 的軟體可以共享同一個 WebView2 組件,Win11 已經內置 WebView2 組件,其他作業系統也可以快速地自動安裝 WebView2 ,
3、WebView2 介面非常簡潔,嵌入其他視窗界面也非常方便,
總結一句話就是:WebView2 簡單、好用、生成軟體體積小,
aardio 標準庫中的 web.view 就是基于 WebView2,WebView2 的介面是如此簡潔,所以我寫的這個庫也只有很少的代碼,因為 aardio 可以將網頁自動內嵌到獨立 EXE 檔案,就可以非常方便地生成獨立 EXE 程式,
? 一個最簡單的程式演示
下面我們用 aardio 呼叫 web.view (WebView2)寫一個最簡單的程式:
import win.ui; /*DSG{{*/ mainForm = win.form(text="WebView2") mainForm.add( btnCallJs={cls="button";text="呼叫 JS 函式";left=461;top=395;right=726;bottom=449;note="點這里呼叫 JavaScript 函式";z=1}; custom={cls="custom";left=17;top=21;right=730;bottom=356;z=2} ) /*}}*/ //創建瀏覽器組件 import web.view; var wb = web.view(mainForm.custom); //匯出本地函式給網頁 JavaScript wb.external = { getComputerName = function(){ return sys.getComputerName(); } } import sys; //寫入網頁 HTML wb.html = /** <html> <head> <script> (async ()=>{ var n = await aardio.getComputerName(); alert(n); })() </script> </head> <body> **/ //回應按鈕事件 mainForm.btnCallJs.oncommand = function(id,event){ //呼叫 JS 函式 wb.xcall("document.write","測驗") } mainForm.show(); win.loopMessage();
對,這就是一個完整程式的源代碼,可以一鍵生成獨立 EXE 檔案,
? 入門
首先點選 「aardio 主選單 > 新建工程 > 視窗程式 > 空白工程」,然后點擊「創建工程」,
如果熟悉網頁前端開發,也可以點擊 「 新建工程 > Web 界面 > WebView2 」創建工程,
雙擊工程入口代碼 main.aardio 打開主視窗,自「界面控制元件」中拖一個 「呼叫 JS 函式」的按鈕上去,再拖一個 custom 控制元件到表單上 —— 用來嵌入網頁:
然后切換到代碼視圖,添加以下代碼創建網頁瀏覽器:
import web.view; var wb = web.view(mainForm.custom);
web.view 的第 1 個引數指定要嵌入 WebView2 的視窗物件,該引數可以是 mainForm.custom 這樣的控制元件視窗,也可以是 mainForm 這樣的表單物件,
下面使用
wb.html = "<html></html>"
就可以寫網頁 HTML 代碼了,
或者使用
wb.go("網址")
可以打開指定的網頁,
使用
import wsock.tcp.simpleHttpServer;
wb.go("\res\index.html");
可以打開資源目錄的網頁,支持SPA 單頁應用,資源目錄可以嵌入 EXE 生成 獨立 EXE 檔案,放心不用多寫其他代碼,
添加下面的代碼匯出 external 物件給網頁 JavaScript :
//匯出本地函式給網頁 JavaScript wb.external = { getComputerName = function(){ return sys.getComputerName(); } } import sys;
在網頁 JavaScript 里可以呼叫上面匯出的 external 物件,不過在 JavaScript 里要用 aardio 這個名字表示 external 物件,網頁代碼如下:
wb.html = /** <html> <head> <script> (async ()=>{ var n = await aardio.getComputerName(); alert(n); })() </script> </head> <body> **/
注意在 aardio 中 /* 注釋 */ 可以作為字串賦值給其他變數,請參考:aardio 編程語言快速入門——語法速覽
要注意所有 aardio 物件在 JavaScript 中都是異步 Promise 物件,如上在 async 函式體內可以愉快地使用 await 呼叫 aardio 函式 —— 這非常方便,
我們在表單設計視圖雙擊「呼叫 JS 函式」按鈕,這會切換到代碼視圖,并自動添加以下回呼函式:
mainForm.btnCallJs.oncommand = function(id,event){ }
用戶點擊按鈕時就會呼叫上面的函式,
小改一下添加 aardio 代碼呼叫 JavaScript 函式:
//回應按鈕事件 mainForm.btnCallJs.oncommand = function(id,event){ //呼叫 JS 函式 wb.xcall("document.write","測驗") }
很簡單,一個程式就寫好了,可以在 aardio 中點擊「運行」按鈕直接運行代碼,也可以點擊「發布」按鈕直接生成 EXE 檔案,
? 如何將網頁顯示在表單的指定位置?并且支持自動縮放?
web.view() 建構式的第 1 個嵌入視窗引數可以是 win.form 物件(獨立視窗),也可以是 custom, static 這樣的普通控制元件物件,例如前面的例子就是將 WebView2 嵌入 custom 控制元件:
import web.view; var wb = web.view(mainForm.custom);
aardio 中的所有控制元件都可以非常方便的支持自動縮放,只要簡單地在表單設計器中選定控制元件,然后在「屬性」面板設定「固定邊距」、「自適應大小」這些屬性就可以,
一個更簡單的方法是在表單設計器上點右鍵,然后在彈出選單中點擊「九宮格縮放布局」—— aardio 將會自動設定所有控制元件的自適應縮放屬性,
至于網頁內容自適應排版很簡單,不需要在 aardio 中撰寫代碼,
? 使用 wb.export 匯出 aardio 函式到 Javascript
前面我們介紹過使用 external 匯出 aardio 函式到網頁 JavaScript ,我們還可以用 wb.export 匯出 aardio 函式,先看例子:
import web.view; var wb = web.view(mainForm.custom); wb.export({ alert = function(msg){ winform.msgbox(msg) }; nativeAdd = function(a,b){ return a + b; } })
注意:
1、wb.export() 匯出的是 JavaScript 全域函式,
2、wb.export() 匯出的函式在 JavaScript 中同樣是異步 Promise 物件,
3、wb.export() 匯出的 Javascript 全域函式, 使用 JSON 自動轉換呼叫引數和回傳值,可以更好的兼容只能支持純 aardio 物件 / 純 JavaScript 物件的代碼,
4、wb.export() 匯出的函式內部禁止呼叫 wb.doScript 或 wb.eval 執行Javascript ,
wb.external 內部是呼叫 wb.exportHostObject() 匯出 aardio 物件,中間不需要經過 JSON 自動轉換,
? 示例:網頁 JavaScript 呼叫本地 Ping 命令
我經常被問到幾個類似的問題:
1、JavaScript 的異步函式太麻煩了,怎樣把他搞成同步的,不用 await ,不用 async ,
2、JavaScript 的異步函式太好用了,怎樣在 aardio 中也這樣搞,如何在 aardio 里 await ,
其實同步有同步的優勢,異步有異步的好處,揚長避短是智慧,倒行逆施最累人,下面我們一起來寫一個在 WebView2 中呼叫本地 Ping 命令的小程式體驗一下,
第一步:創建視窗,
import win.ui; var winform = win.form(text="Ping")
第二步:基于視窗創建 WebView2 瀏覽器組件,
import web.view; var wb = web.view(winform);
第三步:使用 external 物件匯出 JavaScript 可以呼叫的本地函式,
import process.popen; wb.external = { ping = function(domain){ var prcs = process.popen("ping "+ domain); for( all,out,err in prcs.each() ){ wb.invoke("document.body.insertAdjacentText",'beforeend',all); } return "恭喜,事做好了!" } }
在 JavaScript 里用 aardio.ping() 就可以直接呼叫上面的 external.ping() 函式了,
第四步:下面在網頁里寫 JavaScript 來呼叫 aardio 函式,
wb.html = /** <body style="white-space: pre;"><script> doSomething = async() => { var result = await aardio.ping('www.baidu.com'); document.body.insertAdjacentText('beforeend',result); }; </script> <button onclick="doSomething()">開始干活了</ping> **/
就這么短短幾句,一個簡單的程式就完成了,請看運行效果:
上面程式的完整 aardio 源代碼如下:
//創建視窗 import win.ui; var winform = win.form(text="Ping") //嵌入瀏覽器組件 import web.view; var wb = web.view(winform); //匯出 aardio 函式到 JavaScript wb.external = { ping = function(domain){ //同步有同步的優勢,揚長避短是智慧,倒行逆施最累人, var prcs = process.popen("ping "+ domain); for( all,out,err in prcs.each() ){ wb.invoke("document.body.insertAdjacentText",'beforeend',all); } return "恭喜,事做好了!" } } import process.popen; //寫入網頁 HTML wb.html = /** <body style="white-space: pre;"><script> doSomething = async() => { //異步有異步的好處,揚長避短是智慧,倒行逆施最累人, var result = await aardio.ping('www.baidu.com'); document.body.insertAdjacentText('beforeend',result); }; </script> <button onclick="doSomething()">開始干活了</ping> **/ //顯示視窗 winform.show(); //啟動界面訊息回圈 win.loopMessage();
? aardio 呼叫 JS 函式
在 aardio 中可以使用 wb.doScript() , wb.eval() , wb.xcall() 等函式呼叫網頁 JavaScript ,下面看一個在 aardio 中呼叫 xterm.js 的簡單例子:
import win.ui; var winform = win.form(text="xterm") import web.view; var wb = web.view(winform); wb.html = /** <!DOCTYPE html> <head> <meta charset="UTF-8"> <title></title> <link rel="stylesheet" href="https://unpkg.com/[email protected]/css/xterm.css"> <script src="https://unpkg.com/[email protected]/lib/xterm.js"></script> </head> <body style="height:100vh;"> <script> let term = new Terminal(); term.open(document.body); term.write('\x1b[31m紅色字體\x1b[37m測驗') </script> </body> </html> **/ wb.xcall("term.write",'\e[32m綠色字體'); winform.show(); win.loopMessage();
? 無邊框視窗:用網頁實作視窗標題欄
「無邊框視窗」指的是去掉獨立表單默認的邊框與標題欄,然后由程式自行定制邊框與標題欄,
aardio 做這事還是很容易的,首頁在表單屬性中指定「邊框」屬性為 none,
這樣直接運行后顯示的表單就沒有邊框和標題欄了( 按 Alt + F4 關閉視窗 ),
然后添加下面的代碼就可以為表單添加標題欄、標題欄按鈕、陰影邊框、并支持拖動邊框縮放:
import win.ui.simpleWindow;
win.ui.simpleWindow(winform);
win.ui.simpleWindow 的原始碼很簡單,參考其原始碼也可以自己撰寫新的庫定制邊框與標題欄,
這里我們不用上面的方法,而是用網頁實作標題欄,
我們知道網頁繪制一個標題欄與標題欄按鈕很簡單,難點在于怎么在網頁里控制視窗,我們先學習幾個專用于無邊框視窗的 aardio 函式:
winform.hitMax() //模擬點擊最大化按鈕 winform.hitMin() //模擬點擊最小化按鈕 winform.hitClose() //模擬點擊關閉按鈕 winform.hitCaption() //拖動標題欄
下面寫個簡單的例子,先看下運行效果:
WebView2 無邊框視窗示例完整原始碼如下:
import win.ui; /*DSG{{*/ var winform = win.form(text="無邊框視窗";right=759;bottom=469;bgcolor=16777215;border="none") winform.add() /*}}*/ import web.view; var wb = web.view(winform); //匯出為 Javascript 中的 aardio 物件 wb.external = { close = function(){ winform.close(); }; hitCaption = function(){ winform.hitCaption(); }; hitMin = function(){ winform.hitMin(); }; hitMax = function(){ return winform.hitMax(); }; } wb.html = /** <!doctype html> <html> <head> <meta charset="utf-8"> <style type="text/css"> html { margin: 0px; padding: 0px; background-color: #202020; } #title-bar { height: 32px; padding: 0px; margin: 0px; } #title-bar .caption { position: fixed; top: 0px; left: 0px; width: 100%; padding-left: 10px; color: #ADADAD; line-height: 32px; font-size: 14px; cursor: default; user-select:none; } #title-bar .buttons { position: fixed; top: 1px; right: 1px; } #title-bar button { font: 14px Marlett ; color: #F5F5F5; background-color: transparent; border: none; height: 28px; width: 28px; } #title-bar button:hover { background-color: #FF4500; } #title-bar button:active { background-color: #B0451E; color: #C5C5C5; } #main { padding: 12px; color: #C0C0C0; } </style> <script type="text/javascript"> </script> </head> <body> <div id="title-bar" > <div onm ousedown="aardio.hitCaption()">按住這里呼叫 aardio.hitCaption() 拖動視窗 </div> <div > <button id="min-btn" onclick="aardio.hitMin()">0</button> <button id="max-btn" onclick="aardio.hitMax()">1</button> <button id="close-btn" onclick="aardio.close()">r</button> </div> </div> <div id="main"> 1、請指定表單「邊框」屬性為 none ,創建無邊框視窗,<br /> 2、呼叫 win.ui.shadow(winform) 創建陰影邊框<br /> </div> <script src="https://www.cnblogs.com/aardio/archive/2022/09/13/default.js"></script> </body> </html> **/ //添加陰影邊框 import win.ui.shadow; win.ui.shadow(winform); //設定視窗縮放范圍 import win.ui.minmax; win.ui.minmax(winform); //切換最大化、還原按鈕 winform.adjust = function( cx,cy,wParam ) { if( wParam == 0x2/*_SIZE_MAXIMIZED*/ ){ wb.doScript(`document.getElementById("max-btn").innerText="2";`) } elseif( wParam == 0x0/*_SIZE_RESTORED*/ ){ wb.doScript(`document.getElementById("max-btn").innerText="1";`) } }; winform.show(); win.loopMessage();
以上原始碼來自 aardio 自帶范例 > Web 界面 > web.view :
? WebView2 + 前端工程
如果熟悉網頁前端開發,也可以點擊 「 新建工程 > Web 界面 > WebView2 」創建工程,
運行創建的范例工程會顯示幫助:
這些熟悉前端的一看就懂,就不多說了,
注意 WebView2 默認工程的「網頁原始碼」這個目錄的「內嵌資源」屬性為 false —— 也就是說發布后的 EXE 檔案不會包含這個目錄,
而工程中的「網頁」目錄「內嵌資源」屬性為 true —— 也就是說發布后的 EXE 檔案會包含這個目錄,
「網頁」目錄「本地構建」屬性為 true —— 這指的是該目錄下的檔案會無條件添加到發布 EXE 檔案中(不必添加到工程 ),
? 其他瀏覽器組件
aardio 中的瀏覽器組件非常多,用法與 web.view 基本都類似,aardio 甚至可以呼叫作業系統已安裝的 Chrome,Edge 等瀏覽器寫軟體界面,
請參考「 aardio 自帶范例 > Web 界面」:
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/507230.html
標籤:其他
上一篇:vue中代理解決跨域
