ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

PakePlus 桌面端 API 实战:从前端 JS 调用 Tauri 2 全量接口与 PakePlus 自定义 Rust 后端

PakePlus 桌面端 API 实战:从前端 JS 调用 Tauri 2 全量接口与 PakePlus 自定义 Rust 后端 PakePlus 桌面端 API 实战从前端 JS 调用 Tauri 2 全量接口与 PakePlus 自定义 Rust 后端【免费下载链接】PakePlusTurn any webpage/HTML/Vue/React and so on into desktop and mobile app under 5M with easy in few minutes. 轻松将任意网站/HTML/Vue/React等项目构建为轻量级(小于5M)多端桌面应用和手机应用仅需几分钟. https://ppofficial.netlify.app项目地址: https://gitcode.com/GitHub_Trending/pa/PakePlus本文基于 PakePlus 仓库中的官方指南 desktopapi.md 展开讲解在 PakePlus 打包出的桌面应用中如何启用并调用桌面端 API既包括 Tauri 2 通过window.__TAURI__暴露的全量 JS 接口core、app、event、path、menu 等命名空间也包括 PakePlus 自行实现的 Rust 后端命令打开 URL、下载文件、监听下载进度、写入文件、执行系统命令等。读完本文你能在自己的 PakePlus 项目中完整配置并使用这些接口并理解它们在 Rust 端的真实实现与调用链。前提条件必须开启全局 TauriApi桌面端 API 的使用有一个硬性前提必须在 PakePlus 的更多配置中开启全局 TauriApi然后才可以打包发布使用否则接口不会生效。这一点在原文档中以危险提示danger形式特别强调——不开启 TauriApi打包发布后的应用里所有 Tauri 相关调用都将不可用。关于 TauriApi 选项的定位可以结合 config.md 中的配置说明理解该选项“是否启用 TauriApi启用后可以在 js 中调用 tauri 接口”与“脚本文件软件启动时注入执行的 js 脚本”等选项共同构成项目级配置。开启它之后Tauri 的 JS 运行时桥接会被注入到 Webview 中页面脚本才能访问window.__TAURI__。开发过程中的排查技巧可以在 DevTools 控制台直接查看window.__TAURI__对象浏览其中各命名空间的可用接口及其类型定义。结合 tauri.md 中介绍的调试模式Debug Mode / 预览窗口右下角调试按钮可以快速确认当前窗口是否已成功注入 Tauri 环境。桌面 API 的来源与可用插件PakePlus 的桌面端 API 主要由两部分构成Tauri 2 的全量 JS API通过window.__TAURI__命名空间暴露包括 core、app、event、dpi、image、menu、path、webviewWindow 等模块PakePlus 自定义 API一组在 Rust 后端用#[tauri::command]实现的命令前端通过invoke(命令名, 参数)直接调用。从源码结构看PakePlus 在应用构建时注册了一组 Tauri 插件决定了哪些window.__TAURI__.*命名空间实际存在。lib.rs 中依次初始化了以下插件.plugin(tauri_plugin_os::init()) .plugin(tauri_plugin_fs::init()) .plugin(tauri_plugin_dialog::init()) .plugin(tauri_plugin_http::init()) .plugin(tauri_plugin_process::init()) .plugin(tauri_plugin_clipboard_manager::init()) .plugin(tauri_plugin_updater::Builder::new().build()) .plugin(tauri_plugin_store::Builder::default().build())这意味着在打包产物中文件系统window.__TAURI__.fs、对话框、OS 信息、HTTP、剪贴板、Store 数据持久化等插件级 API 均可直接使用。同时lib.rs 的invoke_handler注册了 PakePlus 的全部自定义命令其中包括本文后续重点讲解的open_url、download_file、run_command等.invoke_handler(tauri::generate_handler![ command::cmds::preview_from_config, command::cmds::open_url, command::cmds::open_devtools, command::cmds::update_init_rs, command::cmds::start_server, command::cmds::stop_server, command::cmds::get_machine_uid, command::cmds::compress_folder, command::cmds::decompress_file, command::cmds::download_file, command::cmds::notification, command::cmds::run_command, command::cmds::get_env_var, command::cmds::find_port, command::cmds::get_exe_dir, command::cmds::windows_build, command::cmds::macos_build, command::cmds::linux_build, ])此外start_server/stop_server、compress_folder/decompress_file、notification、get_machine_uid等命令同样在此注册也属于可用的 PakePlus 自定义接口。在 JS 脚本中使用window.TAURI全量命名空间在纯 JS 脚本PakePlus 配置中的脚本文件里可以直接从window.__TAURI__解构出各模块的函数与类。原文档给出的完整解构清单如下覆盖 core、app、event、dpi、image、menu、path、webviewWindow 八个模块// core const { addPluginListener, invoke, Channel, checkPermissions, convertFileSrc, isTauri, PluginListener, requestPermissions, Resource, transformCallback, SERIALIZE_TO_IPC_FN, } window.__TAURI__.core // app const { defaultWindowIcon, fetchDataStoreIdentifiers, getIdentifier, getName, getTauriVersion, getVersion, hide, removeDataStore, setDockVisibility, setTheme, show, } window.__TAURI__.app // event const { emit, emitTo, listen, once } window.__TAURI__.event // dpi const { LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Position, Size, } window.__TAURI__.dpi // image const { Image, transformImage } window.__TAURI__.image // menu const { CheckMenuItem, IconMenuItem, itemFromKind, Menu, MenuItem, NativeIcon, PredefinedMenuItem, Submenu, } window.__TAURI__.menu // path const { appDataDir, appConfigDir, appLocalDataDir, appCacheDir, appLogDir, audioDir, cacheDir, configDir, dataDir, desktopDir, documentDir, downloadDir, executableDir, fontDir, homeDir, pictureDir, publicDir, resourceDir, runtimeDir, templateDir, videoDir, sep, delimiter, basename, dirname, extname, join, normalize, resolve, isAbsolute, localDataDir, resolveResource, tempDir, } window.__TAURI__.path // 调用新建窗口等函数 const { WebviewWindow } window.__TAURI__.webviewWindow其余接口请参考 Tauri 2 官方文档中的 Vanilla JS API 章节。其中几个高频模块的用途简述coreIPC 核心invoke用于调用 Rust 命令Channel用于建立 Rust 到前端的流式回调通道convertFileSrc用于把本地文件路径转换为可在img等标签中加载的协议地址app获取应用标识、版本、Tauri 版本以及窗口show/hide、setTheme、Dock 可见性控制等eventemit/listen/once/emitTo构成跨窗口与前后端的事件总线PakePlus 自定义命令的进度回调如download_progress就是基于它实现的path目录解析downloadDir、appDataDir等与路径工具函数join、dirname、basename等menu原生菜单项的 JS 类可用于动态构造菜单webviewWindowWebviewWindow类用于新建 Webview 窗口。在 Vue/React/Next 等框架中使用如果源项目是 Vue、React、Next 等框架推荐安装对应的 npm 包以获得类型提示与更规范的导入方式// 安装依赖就可以支持类型提示等 // core api pnpm install tauri-apps/api // dialog api pnpm install tauri-apps/plugin-dialog // fs api pnpm install tauri-apps/plugin-fs // os api pnpm install tauri-apps/plugin-os安装后即可用import { invoke } from tauri-apps/api/core、import { writeTextFile } from tauri-apps/plugin-fs等标准写法与 PakePlus 打包时注入的 Tauri 环境无缝衔接前提是同样开启了 TauriApi。PakePlusApi仅适用于 PakePlus 项目的 Rust 后端接口PakePlus 在 Tauri 2 全量 API 之外额外实现了一批 Rust 后端命令供前端 JS 直接invoke调用。原文档对此有明确边界说明这些接口仅能在 PakePlus 项目打包的应用中使用请勿将此 API 用于原生的 Tauri 项目。它们的实现集中位于 cmds.rs以下逐一展开。打开 URL本窗口让_blank链接与window.open都在当前 Webview 内导航而不是弹出系统行为。将以下代码加入脚本即可实现const hookClick (e) { const origin e.target.closest(a) const isBaseTargetBlank document.querySelector( head base[target_blank] ) if ( (origin origin.href origin.target _blank) || (origin origin.href isBaseTargetBlank) ) { e.preventDefault() location.href origin.href } } window.open function (url, target, features) { console.log(open, url, target, features) location.href url } document.addEventListener(click, hookClick, { capture: true })实现思路是在捕获阶段拦截点击事件通过e.target.closest(a)找到命中的a元素同时兼容head base[target_blank]这种全局新窗口声明命中后preventDefault并用location.href在当前窗口内跳转。同时对window.open做猴子补丁把它也转成本窗口导航。这种方式不依赖任何后端接口适用于希望“所有外链都在 App 内打开”的场景。打开 URL新窗口利用 Tauri 的WebviewWindow类可以创建一个全新的 Webview 窗口独立于主窗口const { WebviewWindow } window.__TAURI__.webviewWindow const webview new WebviewWindow(my-label, { url: https://PakePlus.com/, x: 500, y: 500, width: 800, height: 400, focus: true, title: PakePlus Window, alwaysOnTop: true, center: true, resizable: true, transparent: false, visible: true, }) webview.once(tauri://created, function () { // webview successfully created console.log(new webview created) }) webview.once(tauri://error, function (e) { // an error happened creating the webview console.log(new webview error, e) })构造函数第一个参数是窗口 label应用内唯一标识配置对象即 Tauri 2 的窗口配置位置、尺寸、置顶、可调整大小、透明等。创建是异步的通过监听一次性的tauri://created事件确认创建成功、tauri://error事件捕获失败原因。打开 URL默认浏览器如果需要把链接交给操作系统默认浏览器处理例如登录页、支付页等不宜在 Webview 内完成认证的页面调用 PakePlus 自定义命令open_urlconst { invoke } window.__TAURI__.core const hookClick (e) { const origin e.target.closest(a) const isBaseTargetBlank document.querySelector( head base[target_blank] ) if ( (origin origin.href origin.target _blank) || (origin origin.href isBaseTargetBlank) ) { e.preventDefault() invoke(open_url, { url: origin.href }) } } window.open function (url, target, features) { invoke(open_url, { url: url }) } document.addEventListener(click, hookClick, { capture: true })其 Rust 端实现非常轻量见 cmds.rs#[tauri::command] pub async fn open_url(_: tauri::AppHandle, url: String) { open::that(url).unwrap(); }底层使用opencrate 的that函数按操作系统惯用方式唤起默认浏览器Windows 下走 shell 协议、macOS 下走open命令、Linux 下走xdg-open。下载文件调用download_file命令可以把网络文件下载到本地支持多文件并发下载与进度回调const { invoke } window.__TAURI__.core if (__TAURI__ in window) { await invoke(download_file, { url: https://www.baidu.com/img/flexible/logo/pc/result.png, savePath: test.png, fileId: test, }) }参数说明与 cmds.rs 中的签名对应前端 camelCase 到 Rust 端 snake_case 自动转换参数类型说明urlstring要下载的文件网络地址savePathstring保存路径为空时自动回退到系统下载目录下的 URL 末段文件名代码中使用BaseDirectory::Download解析fileIdstring文件标识用于在进度事件中区分多文件下载任务Rust 端实现值得注意的三点行为同名文件自动重命名若目标路径已存在会循环追加数字后缀name1.ext、name2.ext……直到不冲突避免覆盖已有文件流式分块写入基于reqwest经tauri_plugin_http引入的resp.chunk()逐块读取并写盘而非一次性缓冲整个响应每块都上报进度每写入一个 chunk 就通过app.emit(download_progress, ...)向前端广播一次进度事件这正是下一节监听回调的数据来源。监听下载进度下载进度通过 Tauri 事件系统广播。download_progress事件的 payload 由 Rust 端的 DownloadProgress 结构 序列化而来#[derive(Clone, Serialize)] #[serde(rename_all camelCase)] struct DownloadProgress { file_id: String, downloaded: u64, total: u64, }对应前端监听代码const { listen } window.__TAURI__.event listen(download_progress, (event: any) { downloadProgress.value Number( ((event.payload.downloaded / event.payload.total) * 100).toFixed(2) ) })event.payload中可用字段为fileId、downloaded、total字节数。由于多文件下载共享同一事件名实际业务中应结合invoke(download_file, { fileId })传入的标识做过滤只更新对应任务的进度条。注意total依赖服务端返回的Content-Length若响应未携带该头Rust 端会以total: 0兜底前端计算百分比时需自行处理除零情况。写入文本文件使用 Tauri 的 fs 插件把文本内容写入指定目录以下载目录为例const { writeTextFile } window.__TAURI__.fs //or import { writeTextFile } from tauri-apps/plugin-fs; const contents JSON.stringify({ notifications: true }) await writeTextFile(pakeplus.json, contents, { baseDir: BaseDirectory.Download, }) console.log(contents) // Prints string to the consolebaseDir接受BaseDirectory枚举值如BaseDirectory.Download、BaseDirectory.AppData等由 Tauri 解析为各平台的实际目录从而避免手写平台相关路径。写入二进制文件二进制内容如 Canvas 导出的 PNG通过writeFile写入核心是把 Canvas 转成Uint8Array再交给 fs 插件// 创建Canvas const canvas document.createElement(canvas) canvas.width 100 canvas.height 100 const ctx canvas.getContext(2d) // 绘制红色方块 ctx.fillStyle #ff0000 ctx.fillRect(0, 0, 100, 100) // 绘制文字 ctx.fillStyle #ffffff ctx.font 20px Arial ctx.fillText(PakePlus, 30, 50) // 转换为PNG并保存 const blob await new Promise((resolve) { canvas.toBlob(resolve, image/png, 1.0) }) if (!blob) throw new Error(无法创建Blob) const arrayBuffer await blob.arrayBuffer() const uint8Array new Uint8Array(arrayBuffer) console.log(uint8Array11, uint8Array) const file await writeFile(pakeplus_test.png, uint8Array, { baseDir: BaseDirectory.Download, })该模式同样适用于任意 Blob 来源截图、生成图表、音频编码产物等canvas.toBlob→blob.arrayBuffer()→new Uint8Array(...)→writeFile三步即可把内存中的二进制数据落盘。执行命令run_command命令允许前端在系统 shell 中执行命令常用于本机运维类操作或诊断脚本const { invoke } window.__TAURI__.core if (__TAURI__ in window) { invoke(run_command, { command: ls -l }) }从源码实现看cmds.rs该命令按平台分叉执行Windows以powershell -Command command方式启动进程并通过creation_flags(0x08000000)CREATE_NO_WINDOW隐藏控制台窗口避免执行时弹出黑色命令行框非 WindowsmacOS/Linux以sh -c command方式执行输出处理成功时返回 stdout失败时把 stderr 作为错误回传在 Windows 上 stdout/stderr 会先按 GBK 编码解码以兼容中文系统下命令输出的中文内容。#[tauri::command] pub async fn run_command(command: String) - ResultString, String { #[cfg(target_os windows)] let output tokio::process::Command::new(powershell) .arg(-Command) .arg(command) .creation_flags(0x08000000) .output() .await .map_err(|e| e.to_string())?; #[cfg(not(target_os windows))] let output tokio::process::Command::new(sh) .arg(-c) .arg(command) .output() .await .map_err(|e| e.to_string())?; // ... 成功返回 stdout失败返回 stderrWindows 下按 GBK 解码 }总结与适用前提把 desktopapi.md 的完整能力串起来看PakePlus 桌面端 API 的使用路径是更多配置中开启 TauriApi → 通过脚本文件或框架依赖注入 JS →window.__TAURI__调用 Tauri 2 全量接口 /invoke调用 PakePlus 自定义命令。几个关键适用前提需要牢记未开启全局 TauriApi 时所有桌面端 API 在打包发布后均不生效这是最常见的“调不通”原因PakePlus 自定义命令open_url、download_file、run_command等只在 PakePlus 打包的应用中可用不能迁移到原生 Tauri 项目中使用run_command会执行真实系统命令Windows 走 PowerShell其他平台走 shdownload_file会直接写本地磁盘在生产应用中应对入参做必要校验开发期建议先开启调试模式见 tauri.md在控制台检查window.__TAURI__是否存在、事件是否收到再进入打包发布阶段。相关实现与文档可继续在仓库中查阅API 指南 desktopapi.md中文版见 docs/zh/guide/desktopapi.md、配置项说明 config.md、调试与发布模式 tauri.md、Rust 命令实现 src-tauri/src/command/cmds.rs 与插件/命令注册 src-tauri/src/lib.rs。【免费下载链接】PakePlusTurn any webpage/HTML/Vue/React and so on into desktop and mobile app under 5M with easy in few minutes. 轻松将任意网站/HTML/Vue/React等项目构建为轻量级(小于5M)多端桌面应用和手机应用仅需几分钟. https://ppofficial.netlify.app项目地址: https://gitcode.com/GitHub_Trending/pa/PakePlus创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表