前言
一直以来,使用Vue开发桌面应用大部分都是使用基于webview的方案,如electron,tauri等。不依赖webview的,移动端倒有不少,如Weex,NativeScript等,桌面端寥寥无几。
最近,Deft框架完成了Vue3的适配,支持使用Vue+Rust开发跨平台应用,不依赖Webview,目前支持Linux,Windows,MacOS和Android等系统,后续计划将支持鸿蒙和iOS。
快速开始
开始前,系统需要先安装nodejs,Rust,clang14+,如果未安装,直接去官网下载安装即可。
执行下面命令,快速创建新工程,my-vue-app为新工程名称。- npm create deft@latest my-vue-app
复制代码 可以根据自己的喜好选择语言和框架,这里,以TypeScript+Vue为例。
命令执行完后,会在当前目录下创建一个my-vue-app项目,执行下面命令启动项目。- cd my-vue-app
- npm install
- npm run dev
复制代码 启动成功后,会得到如下输出:- ...
- Rspack compiled successfully in 2.31 s
- ==============================================
- Press r to run on this device
- Press a to run on connected android device
- Press q to quit
- ==============================================
复制代码 按r,即可开始构建预览应用。首次构建,需要下载依赖,所以耗时可能会比较长,可以配置cargo镜像提高下载速度。
构建成功后,就能看到预览窗口了,可以直接修改ui目录下的JS/TS文件实时预览效果。
资源占用
在Win11下内存占用仅12M,应用体积包20M,压缩后仅9M。
系统接口调用
开发桌面应用的过程中,有时会遇到调用系统接口的需求,特别是开发本地工具类应用的时候。JS本身不提供系统调用的接口,但是Rust可以非常方便的进行系统接口调用,我们可以使用Rust编写系统调用逻辑,然后提供接口给JS调用,从而扩展JS的能力。
以获取系统和内存信息为例,不同系统提供的底层接口往往不一样,为了抹平不同系统之间的差异,我们可以借助sysinfo库来简化我们的工作。
增加依赖
首先,在命令行切换到我们的工程目录,执行以下命令增加cargo依赖。定义数据交换结构
然后,需要定义Rust和JS之间的通信数据结构,打开项目下的main.rs,增加如下内容:- use deft::js_serialize;
- use serde::Serialize;
- #[derive(Serialize)]
- #[serde(rename_all = "camelCase")]
- pub struct SysInfo {
- pub mem_total: u64,
- pub mem_free: u64,
- pub mem_used: u64,
- pub sys_name: Option<String>,
- pub sys_kernel_version: Option<String>,
- pub sys_os_version: Option<String>,
- pub sys_hostname: Option<String>,
- pub cpu_count: usize,
- }
- js_serialize!(SysInfo);
复制代码 js_serialize宏在这里的作用是使SysInfo结构体能序列化为js对象,而#[serde(rename_all = "camelCase")]可以将字段的下划线命名规则自动转换成小驼峰命名。
使用Rust编写接口
定义好结构体后,就可以使用Rust编写接口了。继续在main.rs增加如下内容:- use deft::js_func;
- use sysinfo::{CpuRefreshKind, MemoryRefreshKind, RefreshKind, System};
- #[js_func]
- pub async fn get_sys_info() -> SysInfo {
- let mut sys = System::new_with_specifics(
- RefreshKind::nothing()
- .with_cpu(CpuRefreshKind::everything())
- .with_memory(MemoryRefreshKind::everything()),
- );
- sys.refresh_all();
- let mem_total = sys.total_memory();
- let mem_used = sys.used_memory();
- let mem_free = sys.free_memory();
- let sys_name = System::name();
- let sys_kernel_version = System::kernel_version();
- let sys_os_version = System::os_version();
- let sys_hostname = System::host_name();
- let cpu_count = sys.cpus().len();
- SysInfo {
- mem_total,
- mem_used,
- mem_free,
- sys_name,
- sys_kernel_version,
- sys_os_version,
- sys_hostname,
- cpu_count,
- }
- }
复制代码 这里有两个点需要关注的:
- 函数使用[js_func]注解,表明这是一个可供js调用的函数。
- 函数前使用async关键字修饰,表明这是一个异步执行的函数,这样即使在函数里执行了耗时任务,也不会阻塞UI线程。如果需要在UI线程同步执行,则去掉async即可。
注册接口
万事具备,只欠东风。最后,我们只需把我们定义的get_sys_info方法注册到js引擎即可。找到main.rs里的init_js_engine方法,增加以下代码:- js_engine.add_global_func(get_sys_info::new());
复制代码 修改UI
接口完成了,现在我们来修改一下我们的UI。
声明接口
如果使用了TS,需要我们声明一下我们使用Rust导出的函数,不然TS编译器会报错。打开deft-env.d.ts文件(或者在项目中新建一个d.ts文件),增加如下内容:- declare interface SysInfo {
- cpuCount: number;
- memTotal: number;
- memFree: number;
- memUsed: number;
- sysName: string;
- sysKernelVersion: string;
- sysOsVersion: string;
- sysHostname: string;
- }
- declare function get_sys_info(): Promise<SysInfo>
复制代码 在JS调用Rust接口
现在我们可以在JS里调用Rust编写的get_sys_info函数了。打开项目里的App.vue文件,script部分修改为:- const sysInfo = ref({} as SysInfo);
- let stopped = false;
- async function updateInfoLoop() {
- if (stopped) {
- return;
- }
- sysInfo.value = await get_sys_info();
- setTimeout(updateInfoLoop, 1000);
- }
- updateInfoLoop();
- onUnmounted(() => {
- stopped = true;
- })
复制代码 这里,使用计时器,不停的刷新数据。
最后,在template里把这个数据渲染出来即可。- <container :>
- <container :>
- <container>
- <container>系统名称:{{sysInfo.sysName}}</container>
- <container>系统版本:{{sysInfo.sysOsVersion}}</container>
- <container>内核版本:{{sysInfo.sysKernelVersion}}</container>
- <container>处理器数:{{sysInfo.cpuCount}}</container>
- <container>总内存量:{{formatMem(sysInfo.memTotal)}}</container>
- </container>
-
- <container :>
- <container :>
- <container>已用内存:{{ formatMem(sysInfo.memUsed) }}</container>
- <container>可用内存:{{ formatMem(sysInfo.memTotal - sysInfo.memUsed) }}</container>
- </container>
- <container :>
- <container :></container>
- </container>
- </container>
- </container>
- </container>
复制代码 这里的container相当于h5里的div。目前所有元素只支持内联样式,不支持通过class等选择器设置样式。
2025.04.20更新:从v0.4版开始,已支持CSS选择器。
最终运行效果:
打包
执行下面命令即可打包打包完成后,会在target/你的系统架构/release/目录下生成一个单独的可执行二进制文件(包含编译后的JS代码),将其拷贝出来即可。
相关链接
Deft框架:https://github.com/deft-ui/deft
Deft文档:https://deft-ui.github.io/guides/what-is-deft/
本文代码:https://github.com/deft-ui/deft-vue-examples/tree/main/system-info
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |