整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          桌面客戶端軟件開發框架

          桌面客戶端軟件開發框架

          面客戶端軟件開發框架是用于創建桌面應用程序的工具集合,它們提供了開發者需要的基本組件、庫和工具,以便于快速構建功能豐富、可靠的桌面應用程序。以下是一些常用的桌面客戶端軟件開發框架,希望對大家有所幫助。北京木奇移動技術有限公司,專業的軟件外包開發公司,歡迎交流合作。

          1.Electron:Electron 是一個開源的跨平臺框架,使用 HTML、CSS 和 JavaScript 構建桌面應用程序。它基于 Chromium 和 Node.js,支持 Windows、macOS 和 Linux 等多個平臺。Electron 由 GitHub 開發,許多知名應用如 Slack、Visual Studio Code 和 Discord 都是使用 Electron 構建的。

          2.Qt:Qt 是一個跨平臺的 C++ 應用程序開發框架,提供了豐富的 GUI 組件和工具包,可用于構建高性能的桌面應用程序。Qt 支持 Windows、macOS、Linux 等主流操作系統,以及移動平臺如 Android 和 iOS。它被廣泛應用于各種行業領域,包括汽車、航空航天、醫療等。

          3.JavaFX:JavaFX 是 Java 平臺的圖形界面框架,用于構建豐富的交互式桌面應用程序。JavaFX 提供了豐富的 UI 控件、動畫效果和多媒體支持,并與 Java 語言緊密集成。JavaFX 可以在 Windows、macOS 和 Linux 等操作系統上運行。

          4.GTK+:GTK+ 是一個跨平臺的 GUI 工具包,使用 C 語言編寫,提供了豐富的界面組件和工具,適用于構建 GNOME 桌面環境下的應用程序。GTK+ 支持 Linux、Windows 和 macOS 等操作系統。

          5.WPF (Windows Presentation Foundation):WPF 是 Microsoft .NET Framework 的一部分,用于構建 Windows 平臺上的富客戶端應用程序。WPF 提供了 XAML 標記語言來定義用戶界面,以及強大的數據綁定和樣式化功能。

          6.Cocoa:Cocoa 是 macOS 平臺上的應用程序開發框架,使用 Objective-C 或 Swift 編程語言。它提供了豐富的 API 和工具,用于構建 macOS 和 iOS 應用程序,并與 macOS 操作系統緊密集成。

          7.Avalonia:Avalonia 是一個跨平臺的 .NET GUI 框架,使用 C# 語言編寫,可用于構建 Windows、macOS 和 Linux 上的桌面應用程序。Avalonia 的設計受到 WPF 和 Xamarin.Forms 的啟發,提供了 XAML 標記語言和 MVVM 模式支持。

          選擇桌面客戶端軟件開發框架時,通常需要考慮開發者的技能水平、項目需求、目標平臺以及性能要求等因素。

          騎士是哈啰的一款終端安全應用,本文主要介紹我們在做新版哈騎士桌面端時的一些技術架構思考和實踐,分享我們沉淀的一些桌面端應用的解決方案和經驗。

          為什么選擇Electron

          前端開發者入門快


          Electron是一個使用 JavaScript、HTML 和 CSS 構建桌面應用程序的框架。嵌入 Chromium 和 Node.js 到 二進制的 Electron 允許您保持一個 JavaScript 代碼代碼庫并創建 在Windows上運行的跨平臺應用 macOS和Linux——不需要本地開發經驗,有了它,前端開發者就可以使用前端開發技術來開發桌面應用了。


          支持跨端&開發效率高


          如上圖所示:

          • Native(C++/C#/Objective-C)不管從原生體驗、包的體積、性能方面來說都是最佳的選擇,但是開發門檻高、迭代速度慢。
          • QT是基于C++的跨平臺開發框架,跨平臺應用十分廣泛(Mac、Windows、ios、Android、Linux、嵌入式),眾所周知的WPS就是用QT開發的。性能很好,甚至于可以媲美原生的體驗,但是整體門檻還是比較高的。
          • NW也是一個跨平臺的框架,但是其社區以及解決方案相對于Electron來說并不是那么強大,而且所有的非javascript編寫的模塊都需要重新用nw-gyp重新編譯,相對于Electron來說,不是那么靈活。
          • Tauri也是一個非?;鸨目缙脚_的桌面端框架,相對于Electron來說還不是那么成熟,生態方面也略顯青澀,兼容性問題有待考證。

          作為一個跨平臺的桌面應用開發框架,Electron 的迷人之處在于,它是建立在 Chromium 和 Node.js 之上的,二位分工明確,一個負責界面,一個負責背后的邏輯。雖然系統間還是會有很大的差異,需要相應地做一些額外處理,使得打包出的應用在不同系統下都能正常運轉,但相比于 80% 都能完全復用的代碼,這些時間和成本都是可以忽略的,開發效率直接翻倍,如果你開發一個不需要太關注底層的桌面端應用,基本不需要做底層的抹平邏輯。



          另外,Electron 是基于 Node.js 的,這就意味著,Node 這個大生態下的模塊,Electron 都可以用。同時,跨平臺也讓 Electron 可同時開發 Web 應用和桌面應用,無論是 UI,還是代碼,很多資源都可以共享,大幅減少了開發者的工作量。


          生態繁榮&案例成熟


          Electron生態的確很強大,各種庫和工具包都為你構建一個桌面端應用提供了很多方案。



          當然,不止如此,現在用Electron做桌面端的案例也非常成熟了。上圖已經說明了Electron應用是有多廣泛了,這其中不乏大名鼎鼎、如雷貫耳的應用,例如 Postman、Skype、VScode 等。而且我敢打賭,各位看官的電腦上一定安裝過用 Electron 開發的應用,如果你用的是 Mac 電腦,請在命令行運行下面的命令來檢測本地采用 Electron 技術開發的桌面軟件:

          for app in /Applications/*; do;[ -d $app/Contents/Frameworks/Electron\ Framework.framework ] && echo $app; done


          Electron生態開發技術選型

          腳手架選型

          關于腳手架的選擇,其實也很多。


          官方提供的有Electron Forge,Electron Fiddle,electron-quick-start,其實如果你的應用不復雜,可以用官方的腳手架生成一個快速上手的模版,然后就可以愉快地開發了。


          當然也有一些開源的腳手架,比如electron-vue或vue-cli-plugin-electron-builder之類的,也可以讓你快速的生成一個固定的模版,然后往里面填充你的內容。


          個人認為,官方的腳手架工具可以用來嘗鮮,學習使用,electron-vue這類工具,如果是在一個企業級的項目中使用,前期會給你帶來便利,但是后期擴展不會太友好,另外就是他們是基于webpack構建的工具,在日常的開發和使用中會覺得編譯得不夠快(相對于Vite)。


          另外就是如果你想自己完成一個項目腳手架(項目框架),完全可以憑借自己的經驗或者參考開源項目的架構自己來完成一個腳手架,一來是為了更加了解Electron的構建原理,二來是可以搭建出適合自己風格項目的腳手架,后期利于擴展和豐富。


          所以我們腳手架的選型就是自己來造一個Electron的項目架構,從package.json開始,用Vite+Electron+React構建一個Electron項目。


          網絡模塊選型

          Electron發送HTTP請求的方案有很多。


          第一種就是渲染進程和主進程分別用相應的請求HTTP請求工具來進行網絡請求,比如渲染進程可以使用fetch,主進程用net模塊。這種方案的優點就是可以把渲染進程和主進程的請求分開,分工明確,而且調試也方便,渲染進程可以直接看network;缺點就是,如果要對請求進行統一封裝的話,比較麻煩。


          第二種就是所有的請求統一封裝,如果你都使用net模塊或者其他的請求工具包對請求進行統一的封裝,然后主進程直接使用,渲染進程調用統一的橋接方法。這種方案就是完全可以統一請求封裝,但是如果想調試的請求的話,不方便,需要在主進程來日志信息。


          第三種就是,直接axios直接一把梭,它既支持node環境,也支持瀏覽器環境。這種方案非常方便,你就按照之前封裝Web應用請求的思路去封裝自己的請求模塊就行,不過需要注意跨域問題。


          對于上面的幾種方案,各有各的優缺點,可以根據自己的場景需求來決定使用哪種方案。我們選擇了axios來設計網絡請求模塊。


          本地數據庫選型

          Electron的本地數據存儲方式也有很多種,可以直接讀寫文件,也可以用相關的庫,方便數據管理。一些庫的對比,詳情:https://www.npmtrends.com/electron-store-vs-lokijs-vs-lowdb-vs-nedb-vs-realm



          綜合來看lowdb更勝一籌,所以選擇lowdb做本地數據庫,非常好的一點是它支持同步,不必擔心數據沒有寫入就進行了下一步需要本地數據的業務操作。


          日志工具選型

          日志工具對Electron的開發也是尤為重要的,可以給你定位到一些表層無法定位的問題,所以一款好的日志工具對開發是非常有幫助的。


          比較常見的日志工具就是electron-log和log4js-node,這兩款日志工具我都有用過??梢钥聪耼pm的排行,這里把express-winston和logging也加上看一下,詳情:https://npmtrends.com/electron-log-vs-express-winston-vs-log4js-vs-logging。



          這里簡單說一下electron-log和log4js-node的比較,兩者上手都比較簡單,log4js-node暴露的API 非常多,electron-log就稍顯遜色了,另外最直觀的感受就是,electron-log的日志文件路徑不好找,暫時沒發現自定義日志路徑的方法,log4js-node有相應的方法,而且你可以自定義各種文件類型。


          根據使用體驗,覺得log4js-node更好,推薦log4js-node。


          構建工具選型

          三種構建工具electron-builder, electron-forge, electron-packager 對比一下。



          從這個排行來看electron-builder的確很強,electron-forge最近又更新大的版本,不過沒有嘗鮮,我在electron-builder上倒是踩了不少坑,可以分享給大家。所以我在開發的時候選擇的構建打包工具是electron-builder,它把整套解決方案都集成了,包括打包、更新、簽名、分發,基本的鉤子和配置都有相應的暴露。


          核心架構實現

          架構概覽


          我們整個框架是基于Eletcorn + Vite構建的,在底層依賴的安全能力和存儲模塊的基礎設施之上設計了一層基礎框架,實現構建打包,架構分層的設計,然后給整個桌面應用提供一些應用管理能力和GUI管理相關的能力,最上層就是為了一些業務場景提供的一些應用能力,包括核心的幾個應用和主要的策略引擎應用(終端策略和合規策略)。


          開發構建

          Electron是多進程架構的體系,所以我們在開發構建的時候就是構建多個進程來實現我們的應用。核心思路是通過Vite構建三個進程:渲染進程,任務進程,主進程,然后最后將三個進程融合起來,就形成了一個應用。核心代碼如下:



          幾個注意點:

          • 我們這里利用了writeBundle,就是等chunk都寫入文件后,再啟動Electron進程。
          • 這里沒有利用Electron的命令啟動,而是通過Node.js的child_process模塊的spawn方法啟動Electron子進程,主要是因為我們需要依賴開發環境的渲染進程。
          • 另外就是config/vite/main.js中需要對rollupOptions的external進行electron的配置,把導入包轉成外部依賴,不然在啟動Electron會找不到Electron的路徑。
          • 在createMainServer中我們注入了全局可使用的變量,以便Electorn加載頁面的時候可以使用這些變量。


          架構分層


          因為需要跨端開發,Mac和Windows有些底層模塊的實現還是有不一樣的地方,所以我們在開發設計的時候將代碼進行了分層設計,這樣至上而下的調用在上層看來是一樣的,所以我們需要磨平端上底層的差異,現階段我們底層模塊的實現是通過目錄來嚴格區分的,這樣在開發一個底層的功能的時候就可以做到各段相互不影響。


          打包升級

          桌面客戶端相當于傳統的Web應用在打包和更新這一塊還是有非常大的不同的,傳統的web應用幾乎不用所謂的升級,瀏覽器刷新頁面即可,但是桌面客戶端就需要完整的給用戶一個可以立即執行的安裝應用程序,而且還要可持續迭代和更新,所以在打包升級這一塊,我們也是踩了不少坑。



          1. 關于打包

          打包其實Electron的生態也是非常成熟的,如上面提到的構建技術選型,我們選擇的是electron-builder,它提供了一套打包構建升級的流程,暴露了很多API,傻瓜式的配置就基本可以讓你實現一個應用的打包了,唯一麻煩的就是簽名和認證應用。


          在Windows端我們使用pfx格式的證書進行認證,在進行打包的時候會和證書客戶端軟件交互,完成各個文件的簽名,這樣用戶使用客戶端的時候就是簽名過的軟件了。


          在Mac端我們需要使用蘋果認證的開發者證書進行簽名和認證,配置相應的identity后,構建打包的時候會直接跟你本地的證書進行交互,然后對文件進行簽名,當前我們還需要讓應用可以不必嚴格使用 MAP_JIT 標識也能寫入和運行內存內容。所以需要加入entitlements和entitlementsInherit。

          <?xml version="1.0" encoding="UTF-8"?>
          <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
          <plist version="1.0">
            <dict>
              <key>com.apple.security.cs.allow-unsigned-executable-memory</key>
              <true/>
            </dict>
          </plist>


          到這一步其實Mac端的軟件簽名就完成了,但是如果應用想App Store上架的話還需要對應用進行公證。公證主要是使用electron-notarize來進行公證,啟用afterSign即可,

          afterSign: './script/notarize.js',


          下面的Apple ID就是你的開發者賬號,appleIdPassword需要生成一個專用的應用密碼,不要使用你本來的Apple ID密碼。

          const { notarize }=require("electron-notarize");
          
          
          exports.default=async function notarizing(context) {
            const { electronPlatformName, appOutDir }=context;
            if (electronPlatformName !=="darwin") {
              return;
            }
          
          
            const appName=context.packager.appInfo.productFilename;
          
          
            console.log(\`公證中...\`)
          
          
            return await notarize({
              appBundleId: "mac.hellobike.knight",
              appPath: \`${appOutDir}/${appName}.app\`,1
              appleId: "XXXXX@outlook.com",
              appleIdPassword: "XXXXX",
            });
          };


          notarize會根據你的配置去校驗你的應用是否可以公證成功,公證的時候會和蘋果的服務器進行通訊,所以需要保持網絡不要斷開,成功或者失敗之后都會發送相應的郵件到你的開發者郵箱里面。


          到這里打包的核心工作就做完了,如果你需要其他個性化配置,參考electron-builder官方的文檔即可。


          2. 關于升級

          升級我們在Mac和Windows上的實現各有不同,因為相比于傳統的軟件,我們哈騎士會一直?;钤谟脩舻倪M程中,所以在更新升級的時候也會打破原本Electron升級的機制。


          在Windows上其實還好,可以利用electron-updater本身的生命周期來完成下載,更新,重啟應用,因為Windows的?;钍怯昧硗獾姆諄韺崿F的,所以并不會對整個更新周期產生破壞性的影響。


          但是Mac端的?;顚崿F是打破了electron-updater本身的生命周期的,探究其源碼會發現Electron自己的升級服務其實也是一個?;畹膽梅眨栽谏壷靶枰獙⑵銴ill后才能完成哈騎士自己本身的更新邏輯,另外就是文件占用和鎖定的問題,為此我們自研了一套更新腳本程序結合electron-updater的下載更新的能力實現了Mac端軟件的升級。


          核心能力沉淀

          基礎能力

          我們在做哈騎士客戶端的時候,也沉淀了一些與業務無耦合的組件和工具類,這些組件和工具在桌面端應用的場景都比較通用。



          • 本地數據庫管理
            本地數據存儲是業務場景中隨處可見的重要功能。為此,我們封裝了常用的增刪改查數據庫的能力,并提供給各個進程使用,以實現數據持久化存儲。
          • 底層橋接
            底層橋接是解決Electron和Node無法覆蓋所有應用場景的必要手段。我們在橋接層封裝了三種橋接模式,分別為渲染進程調用的jsBridge能力、主進程調用dll和dylib插件的能力,以及橋接rust程序的能力。這三種模式基本上可以解決所有技術瓶頸。
          • 客戶端請求
            客戶端請求模塊也是至關重要的。我們將其封裝成了通用的http請求庫,支持主進程、渲染進程和任務進程的調用,以抹平上層調用的差異性。
          • 任務管理
            由于業務場景和客戶端的特殊性,我們經常需要進行本地任務管理。因此,我們將任務管理模塊封裝成了通用的工具類,以支持對任務的注冊、啟動、停止和銷毀等各項生命周期的管理。


          應用能力

          在上面這些基礎能力的組合應用下,我們形成了一個強大的策略引擎應用。



          該策略引擎應用實現了端上任務調度和分發功能。首先接收后臺配置的策略信息,然后生成對應的任務,并分發到各個子任務中心以執行對應的策略。最后,將策略執行情況報告給服務端。


          總結

          Electron在哈騎士的應用非常成功,雖然在使用過程中遇到了一些問題,但不可否認它是目前最適合我們業務目標和開發資源的框架。使用Electron使需求交付效率得到了很大的提升。


          我們也將持續關注性能和穩定性的優化、桌面端全鏈路日志的完善以及增量更新升級能力等方面的改進。

          作者:徐濤燾

          來源:微信公眾號:哈啰技術

          出處:https://mp.weixin.qq.com/s/8v5lyl-yI4AMxQgSwDmkWw

          ebView2 是越來越香了。

          WebView2 不但是 Win11 自帶的系統組件,Win10 也已經自動推送安裝。即使是少量沒有安裝 WebView2 的系統 —— 使用 aardio 中的 web.view 也會自動安裝( 不需要寫任何代碼 )。

          我用 WebView2 開發了很多項目,不得不說 WebView2 穩定可靠、性能強悍,接口簡潔,是真的讓人省心。

          htmx.js

          這里介紹一個適合用于 WebView2 的極簡前端組件 htmx.js ,這個組件最大的特色就是簡單,一學就會,也很容易理解。

          我們正常瀏覽一個網頁的過程是在瀏覽器里輸入網址,向 HTTP 服務器發送請求。然后服務器返回 HTML 代碼,瀏覽器顯示頁面。

          但是 htmx.js 腦洞大開,讓網頁上的每一個 HTML 節點都可以向服務器發送請求并獲取 HTML,并實時更新頁面上指定的節點。而且不需要寫任何 JavaScript 代碼。

          起步

          首先我們打開 aardio ,創建 WebView2 工程并選擇 htmx.js 模板:

          生成的工程如下:

          點『運行』可直接測試效果,點『發布』可生成獨立 EXE 文件 。

          在工程管理器中右鍵點『網頁』彈出菜單,然后點『用外部編輯器打開』,如果安裝了 VS Code 會使用 VS Code 打開網頁目錄。

          在 VS Code 中點擊并打開 index.html 源碼:

          htmx.js 基礎

          打開 index.html ,先看最簡單的 htmx.js 示例:

          <button hx-get="/api/index.aardio" 
              hx-swap="innerHTML" 
              hx-trigger="click" 
              hx-target="#info-div"  >
              點這里發送 GET 請求
          </button><br>
          
          <div id="info-div"></div>

          注意看凡是 "hx-" 前綴的屬性都是用于 htmx.js 。

          hx-trigger 用于指定在什么事件發生時觸發 HTTP 請求,例如:

          hx-trigger="click" 

          表示在 click 單擊事件發生時觸發請求。

          hx-trigger 可使用標準網頁事件名,常用事件如下:

          • load - 網頁元素首次加載時觸發請求。
          • click - 單擊時觸發請求這是除表單,表單控件之外所有元素的默認事件。
          • change - 控件值改變時觸發請求。input,textarea,select 等控件的默認事件
          • submit - 提交表單時觸發請求。表單的默認事件。
          • keydown - 按鍵時觸發請求。
          • keyup - 放開按鍵時觸發請求。
          • mouseenter - 鼠標進入時觸發請求。
          • mouseleave - 鼠標離開時觸發請求
          • every 時間 - 定時觸發請求,例如 hx-trgger="every 1s" 指定每隔 1 秒發送一次請求。

          事件名后面還可以添加修飾器,例如修飾器 once 表示只允許觸發一次 :

          hx-trigger="click once" 

          其他事件修飾器:

          • changed - 只有在元素的值更改時發出請求
          • delay:延時 - 在指定的延時后發出請求,例如 hx-trgger="load delay:1s" 指定元素加載后延遲 1 秒發送請求。如果服務端不斷地返回相同 HTML 并替換節點自身,也可以實現輪詢的效果( aardio 后端可以控制何時停止輪詢 )。
          • throttle:延時 - 節流,避免在指定時間內重復請求
          • from:CSS選擇器 - 監聽指定元素上的事件。

          下面的 HTML 使用了多個事件修飾器:

          <input type="text" 
            hx-trigger="keyup changed delay:500ms"
            hx-post="/api/index.aardio" >

          這表示在按鍵放開( keyup ),文本框的內容發生改變( changed )時觸發,并且延時 500 毫秒再發送請求。

          hx-get 則指定要請求的是哪個后端頁面,例如:

          hx-get="/api/index.aardio" 

          表示事件觸發時,請求 "/api/index.aardio" 這個頁面。因為 aardio 在啟動 SPA 應用時自動指定了后端根目錄為 "/web",所以實際請求的是 "/web/api/aardio" 。

          而 hx-swap 則指定要將返回的 HTML 寫入到哪里,"innerHTML" 指定是更新網頁節點內部 HTML,"outerHTML" 指定替換目標網頁節點的全部 HTML ,其他還有 "afterbegin" , "beforebegin" , "beforeend" , "afterend" , "none" 。這些看名字就知道是什么作用,就不解釋了。

          hx-target 屬性用 CSS 選擇器指定要寫入的網頁節點,例如:

           hx-target="#info-div" 

          指定服務器返回的 HTML 寫入 id 為 "info-div" 的節點。如果省略 hx-target 屬性表示寫入目標是當前節點自身。

          hxmx.js 在更新 HTML 時,如果發現新舊 html 中有 id 相同的元素會進行優化并平滑顯示。

          看到這里,htmx.js 您已經會用了。

          雖然 htmx.js 文檔里有更多花式用法,但一般可能用不上。有些事搞太復雜了也不一定是好事。

          htmx.js + aardio 后端

          aardio 提供了嵌入式 HTTP 服務器,可以直接使用 aardio 代碼寫網頁,支持與 PHP 類似的模板語法。

          aardio 的模板語法很簡單,aardio 代碼寫在 <? ?> 內部,而 HTML 代碼寫在 <? ?> 外部就可以了。實際上 <? ?>外部的代碼被轉換為了 aardio 中 print 函數的參數。

          例如服務端有下面的 aardio 代碼:

          <span>abc</span>
          <?
            response.write("123")
          ?>

          運行后會自動轉換為純 aardio 代碼如下:

          print("<span>abc</span>");
          response.write("123");

          在 HTTP 后端中,print 函數實際上就是指向用于向 HTTP 客戶端輸出數據的 response.write() 函數。

          在 HTTP 后端有兩個最常用的對象,request 對象包含了所有 HTTP 請求信息,而 response 對象為 HTTP 響應對象,用于向客戶端發送數據。

          打開 aardio 自帶「工具 > 庫函數文檔」,點擊 fastcgi.client 的文檔可以查看 request, response 對象的所有屬性與方法。aardio 中的所有 HTTP 服務端實現都統一兼容 fastcgi.client 文檔規定的 request, response 用法。

          也可以參考 aardio 開始頁的 《 aardio 網站開發、FastCGI開發入門教程 》。至于 aardio 模板語法,請參考 《 aardio 語法與使用手冊 > aardio 語言 > 模板語法 》

          aardio 的模板語法不僅僅可以用于寫 HTTP 后端,也不僅僅是可以用于輸出 HTML,實際上可以用于生成任何字符串。aardio 中的很多功能都支持這種模板語法,例如運行時編譯 C# 代碼就支持用 aardio 模板語法生成 C# 代碼。另外 aardio 提供 string.loadcode() 函數可以直接解析 aardio 模板并返回字符串。

          htmx.js指示動畫,aardio 后端線程

          這里要注意,上面范例工程默認導入的 HTTP 服務器是:

          wsock.tcp.simpleHttpServer;

          這是一個多線程的 HTTP 服務端,每次被請求執行的 aardio 代碼都是在后臺線程中運行。aardio 多線程開發要注意的是每個線程都運行在獨立的環境,全局變量是相互隔離的,這個限制實際上讓 aardio 的多線程開發更簡潔,坑更少,具體請參考 aardio 自帶「范例程序 > aardio 語言 > 多線程」。

          如果改為 wsock.tcp.asynHttpServer 則是單線程異步的 HTTP 服務器。

          下面我們仍然使用默認的 simpleHttpServer 。多線程的好處是耗時操作不會卡界面。后端在進行耗時操作時,網頁前端通常需要顯示一個動畫,htmx.js 做這事就很簡單。

          我們只要簡單的修改一下前面講過的網頁代碼如下:

          <button hx-get="/api/index.aardio" 
              hx-indicator="#indicator" >
              點這里發送 GET 請求
          </button><br>
          
          <img id="indicator" 
              class="htmx-indicator" 
              src="/images/loading.gif"/>

          主要是增加了 hx-indicator 屬性,該屬性的值用一個 CSS 選擇器指定了發送 HTTP 請求時要顯示的 HTML 元素,這里指定的是 id 為 "indicator" 的元素。

          實際上我們可以自定義這個請求動畫的樣式,我們打開樣式文件 index.css 添加下面的樣式:

          .htmx-indicator{
              display:none;
          }
          .htmx-request.htmx-indicator{
              display:inline;
          }

          在發送請求時,網頁上被設定的指示元素會自動添加 CSS 類 "htmx-request",HTTP 請求結束會移除該類。

          然后我們打開對應的 aardio 后端代碼 /web/api/index.aardio ,輸入以下代碼:

          <span>
          <?
          
          if( request.method=="GET"){
              
              /*
              這是多線程后端,
              這里等 2 秒,網頁會顯示加載動畫
              */
              sleep(2000);
              
              response.write( time() )    
          } 
          ?></span>


          上面的代碼的作用是:如果收到 GET 請求,線程就休眠 2 秒以模擬耗時操作。然后輸出當前時間。

          我們運行一下看看效果:

          請求參數

          htmx.js 提交請求的節點如果是一個表單控件,只要指定 name 屬性 —— 就會自動以該名字發送請求參數,參數值就是控件的值。

          如果提交請求的節點是表單,則 HTTP 請求參數為表單內所有控件的值。

          也可以在節點的 hx-vals 屬性中用一個 JSON 對象指定請求參數,例如網頁這樣寫:

          <button hx-get="/api/index.aardio" 
              hx-vals='{"myVal": "值"}'>
              點這里發送 GET 請求
          </button><br>

          aardio 后端就可以使用:

          request.get["myval"]

          取到 HTTP 請求參數 myval 的值。

          如果使用 POST 發送請求,例如:

          <button hx-post="/api/index.aardio" 
              hx-vals='{"myVal": "值"}'>
              點這里發送 GET 請求
          </button><br>

          那么 aardio 后端可以使用

          request.post["myval"]

          取到 HTTP 請求參數 myval 的值。

          在 aardio 后端使用:

          request.query("myval")

          可以取到 GET 或 POST 發送的 myval 參數值。

          hx-vals 還可以通過加上 javascript: 或者 js: 前綴后使用 JS 對象返回請求參數,例如:

          <button hx-get="/api/index.aardio"  
              hx-vals='javascript:{myVal: "值"}'    >
              點這里發送 GET 請求
          </button> 

          web.form 也玩 htmx.js

          有趣的是 web.form 也可以支持 htmx.js 。

          web.form 是基于系統自帶的 IE 內核控件,注意系統雖然刪除了 IE 瀏覽器,但 IE 控件屬于系統組件,Windows 有說明該控件不會被移除。IE 控件的好處是從 XP 到 Win11 所有操作系統都自帶。

          而且 IE 控件很輕量,與本地程序交互的接口也非常方便。Win10 ,Win11 自帶的是 IE11 內核,寫寫一般的網頁還是很好用的。至于 Win7 —— 因為只有極低的份額,一般軟件不用考慮。

          htmx.js 最后一個支持 IE 11 的版本是 1.6.1 ,這個足夠用了。前面說過我們需要的只是局部請求刷新的功能,其他功能我們用不上,所以追新無意義。

          首先我們打開 aardio 工程向導,選擇「 Web 界面 > Web Form 」然后創建工程即可,新版工程模板默認就是使用 htmx.js 。

          其他 HTML 代碼寫法與前面介紹的 WebView2 基本一樣。不過 web.form 本就支持 EXE 內嵌資源文件,所以默認并不會啟動 HTTP 服務器,需要多寫幾句代碼。

          打開工程的 webPage.aardio 源碼:

          可以看到源碼中是如下啟動 HTTP 服務器的:

          import web.form;
          var wb=web.form(winform); 
          
          //多線程后端
          import wsock.tcp.simpleHttpServer;
          wsock.tcp.simpleHttpServer.documentBase="\web"
          var indexUrl=wsock.tcp.simpleHttpServer.startUrl("\index.html")
           
          wb.go(indexUrl);

          我并沒有把這幾句代碼封裝到 wb.go() 函數中。

          有些新手總以為代碼越少越好,其實并非如此,有時候多寫幾句更容易看清楚代碼的思路,更容易理解我們正在使用的技術。

          下面我們看下 web.form + htmx.js 范例的運行效果:

          上面示例程序的主窗口是使用 win.ui.tabs 做的,只有其中一個標簽頁用到了網頁。

          其實一般桌面軟件的界面并不是一定要全部使用網頁實現。有時候我們將界面中適合用網頁呈現的部分用網頁做,可能會更好。

          我們在使用任何技術時,都要考慮一下適不適合。沒有一樣技術能適合做所有的事,多個選擇總是好事。


          主站蜘蛛池模板: 精品少妇一区二区三区在线| 麻豆视频一区二区三区| 成人乱码一区二区三区av| 国产精品视频一区| 在线视频一区二区三区三区不卡 | tom影院亚洲国产一区二区 | 精品一区二区三区无码免费直播| 国产精品视频分类一区| 国产精品日韩一区二区三区| 久久无码人妻精品一区二区三区| 综合久久久久久中文字幕亚洲国产国产综合一区首 | 日韩内射美女人妻一区二区三区| 亚洲中文字幕一区精品自拍| 国产无码一区二区在线| 久久精品国产AV一区二区三区| 一区二区三区在线观看中文字幕 | 日韩一区二区三区电影在线观看 | 中文无码一区二区不卡αv| 视频一区视频二区日韩专区| 无码一区二区三区AV免费| 亚洲一区精品中文字幕| 国产精品 视频一区 二区三区| 国产主播在线一区| 亚洲一区精彩视频| 亚洲一区二区三区高清视频| 亚洲熟女一区二区三区| 亚洲AV永久无码精品一区二区国产| 成人精品一区二区激情| 国内精自品线一区91| 久久久久人妻精品一区三寸| 国产精品视频一区| 精品久久综合一区二区| 国产精品一区二区AV麻豆| 国产在线第一区二区三区| 国产aⅴ一区二区| 日本高清成本人视频一区| 一区二区三区国产精品 | 国产一区二区精品尤物| 日本大香伊一区二区三区| 鲁丝片一区二区三区免费| 69福利视频一区二区|