当前位置: 首页 > news >正文

【一起学Rust | 框架篇 | Tauri2.0框架】tauri中rust和前端的相互调用(rust调用前端)

在这里插入图片描述

文章目录

    • 前言
    • 1. rust中调用前端
    • 2. 如何向前端发送事件
    • 3. 前端监听事件
    • 4. 执行js代码


前言

近期Tauri 2.0 rc版本发布,2.0版本迎来第一个稳定版本,同时官方文档也进行了更新。Tauri是一个使用Rust构建的框架,可以让你使用前端技术来构建桌面应用程序。

在先前的开发工作中,由于Tauri本身有整合浏览器的能力,有相当多的部分是在前端能力的基础上实现的,比如说web serial api,又或者web camera api,这些api在前端中调用是相当容易的,但是容易使用并不代表它就一定是可靠的,比如web serial api的断帧问题就无解,即使你写循环去补,也会出现错帧的情况,对于小数据来说已经完全够用了(30个字节以下),对于数据量稍微多一点,就要分帧处理,且很混乱。所以,对于这种东西,最好也就是使用rust来实现了。当然,tauri也并不是一直都好的,tauri官方做出一堆插件,这些插件很容易就可以使用,相当于用户只需要关心前端开发,但是这些插件有些使用的谷歌服务,谷歌服务在国内无法访问,所以体验也不好。这也不好,那也不好,究竟怎么才能行呢?期待tauri以后能解决这些问题,起码就目前而言,调用rust能力是个比较靠谱一点的方案,可惜东西需要自己写。

吐槽完毕,开始进入正题。

在使用tauri进行开发时,前后端通信是相当重要的,可以说是贯穿应用开发的整个流程,所以,在此之前,你需要了解tauri前后端是如何通信的。官方在更新了v2的文档后,提供了如下图片,很清晰,轻松就能看懂。

tauri事件机制

从图上可以看出,tauri的事件是可以双向传递的,这就对前后端通信很有帮助,一旦你理解了这个图,tauri开发你就懂了一大半了。

1. rust中调用前端

根据前面图中的描述,我们可以知道,要想在rust中调用前端的方法,要在rust中向前端发送一个事件,前端监听这个事件,当前端监听到这个事件后,前端就可以进行相应的处理,这样就实现了rust调用前端的功能。

要实现这些功能,那么就需要解决以下问题:

  1. 如何向前端发送事件
  2. 前端如何监听事件

我们来挨个解决这些问题。

2. 如何向前端发送事件

向前端发送事件的能力是由AppHandle来提供的,AppHandle是tauri的核心,它提供了很多能力,包括前后端通信,窗口管理,应用生命周期管理等等。所以,要向前端发送事件,就需要先获取到AppHandle。

获取AppHandle的方式很简单,不需要我们手动来加很多东西,只要在command中添加参数,在程序执行的时候会自动注入AppHandle,然后我们就可以直接使用AppHandle了。

在获取到AppHandle后,可以调用emit方法来触发前端事件,emit方法接受两个参数,第一个参数是事件名,第二个参数是事件数据,事件数据可以是任意类型,tauri会自动将数据转换为前端可以识别的数据类型。

以下是示例代码

#[tauri::command]
fn send_event(app_handle: tauri::AppHandle, message: String) {app_handle.emit("rust_event", message).unwrap();
}

事件负载数据最好使用struct,因为官方就是这么做的,struct支持序列化,且代码美观,易读懂。

#[derive(Clone, Serialize)]
#[serde(rename_all = "camelCase")]
struct DownloadStarted<'a> {url: &'a str,download_id: usize,content_length: usize,
}

在这里有一点是要注意的,也是可能你很需要的,就是触发事件分为

  1. 触发全局事件
  2. 触发指定Webview的事件

上述给的例子就是触发全局事件,你只要在webview中监听这个事件,就可以触发这个事件,如果你想要指定,那么要使用emit_to方法,这个方法接受三个参数,第一个参数是事件名,第二个参数是webview的id,第三个参数是事件数据,webview的id可以通过tauri::Window来获取,tauri::Window可以通过tauri::WindowBuilder来创建,tauri::WindowBuilder可以通过tauri::Builder来创建,tauri::Builder可以通过tauri::Builder::default()来创建。

以下是示例代码

use tauri::{AppHandle, Emitter};#[tauri::command]
fn login(app: AppHandle, user: String, password: String) {let authenticated = user == "tauri-apps" && password == "tauri";let result = if authenticated { "loggedIn" } else { "invalidCredentials" };app.emit_to("login", "login-result", result).unwrap();
}
use tauri::{Emitter, EventTarget};#[tauri::command]
fn download(app: tauri::AppHandle) {for i in 1..100 {std::thread::sleep(std::time::Duration::from_millis(150));// emit a download progress event to all listenersapp.emit_to(EventTarget::any(), "download-progress", i);// emit an event to listeners that used App::listen or AppHandle::listenapp.emit_to(EventTarget::app(), "download-progress", i);// emit an event to any webview/window/webviewWindow matching the given labelapp.emit_to("updater", "download-progress", i); // similar to using EventTarget::labeledapp.emit_to(EventTarget::labeled("updater"), "download-progress", i);// emit an event to listeners that used WebviewWindow::listenapp.emit_to(EventTarget::webview_window("updater"), "download-progress", i);}
}

或者使用 emit_filter来指定

use tauri::{Emitter, EventTarget};#[tauri::command]
fn download(app: tauri::AppHandle) {for i in 1..100 {std::thread::sleep(std::time::Duration::from_millis(150));// emit a download progress event to the updater windowapp.emit_filter("download-progress", i, |t| match t {EventTarget::WebviewWindow { label } => label == "main",_ => false,});}
}

指定窗口label需要创建多个窗口,这个目前还未涉及到,后面更新文章添加相关管内容(多窗口管理)。

3. 前端监听事件

在tauri中前端监听事件是非常容易的,tauri导出了一个listen对象,可以监听事件,在使用的时候绑定你所需要的方法就好了。

以下是示例代码(监听全局事件)

import { listen } from '@tauri-apps/api/event';type DownloadStarted = {url: string;downloadId: number;contentLength: number;
};listen<DownloadStarted>('download-started', (event) => {console.log(`downloading ${event.payload.contentLength} bytes from ${event.payload.url}`);
});

监听指定webview的事件

import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow';const appWebview = getCurrentWebviewWindow();
appWebview.listen<string>('logged-in', (event) => {localStorage.setItem('session-token', event.payload);
});

监听事件这个对象会在应用的整个生命周期监听事件,如果需要不监听了,那么你可以接受监听事件的返回值,执行

import { listen } from '@tauri-apps/api/event';const unlisten = await listen('download-started', (event) => {});
unlisten();

如果监听的事件只需要执行一次,那么只需要调用once方法即可

import { once } from '@tauri-apps/api/event';
import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow';once('ready', (event) => {});const appWebview = getCurrentWebviewWindow();
appWebview.once('ready', () => {});

后续还有通道channel,支持大数据传输,这个目前还未涉及到,也没有找到应用场景,如果遇到了我会写一下这里的坑。

4. 执行js代码

既然是webview,肯定少不了执行js代码的部分(很期待能控制网络请求,那可就太爽了),通过这个,一些网页自动化插件什么的,很轻松就能实现了,我觉得后面可以做个玩玩。

以下是示例代码

use tauri::Manager;tauri::Builder::default().setup(|app| {let webview = app.get_webview_window("main").unwrap();webview.eval("console.log('hello from Rust')")?;Ok(())})

前端调用rust可以使用command,也可以使用event,这个内容放到下期。(你英文好的话也可以直接看官方文档。)

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • [已解决]mac远程连接windows桌面:parallels client连接遇到的问题
  • repo的patch转换成git am能打的patch
  • 三级_网络技术_43_综合题(报文)
  • USB设备驱动代码分析(鼠标)
  • 如何设置PowerBI报告展示在屏幕的大小?
  • 【AI赋能游戏】《黑神话:悟空》专属黑悟空无限创意生成器!(整合包分享)
  • 选择排序(直接选择排序和堆排序)
  • Go Convey测试框架入门(go convey gomonkey)
  • 特殊类设计和类型转换
  • 进阶SpringBoot之 SpringSecurity(2)用户认证和授权
  • TIM输出比较之PWM驱动直流电机应用案例
  • UEFI启动流程
  • 《黑神话:悟空》到底是用什么语言开发的
  • 从0到1构建视频汇聚生态:EasyCVR视频汇聚平台流媒体协议支持的前瞻性布局
  • 依靠 VPN 生存——探索 VPN 后利用技术
  • 【vuex入门系列02】mutation接收单个参数和多个参数
  • 【跃迁之路】【735天】程序员高效学习方法论探索系列(实验阶段492-2019.2.25)...
  • 10个确保微服务与容器安全的最佳实践
  • ABAP的include关键字,Java的import, C的include和C4C ABSL 的import比较
  • Android Volley源码解析
  • CODING 缺陷管理功能正式开始公测
  • es的写入过程
  • iOS动画编程-View动画[ 1 ] 基础View动画
  • Java IO学习笔记一
  • Java方法详解
  • JDK 6和JDK 7中的substring()方法
  • js对象的深浅拷贝
  • JS进阶 - JS 、JS-Web-API与DOM、BOM
  • JS学习笔记——闭包
  • Phpstorm怎样批量删除空行?
  • PV统计优化设计
  • Redux系列x:源码分析
  • Spring Cloud Alibaba迁移指南(一):一行代码从 Hystrix 迁移到 Sentinel
  • SpringCloud集成分布式事务LCN (一)
  • SSH 免密登录
  • STAR法则
  • 百度贴吧爬虫node+vue baidu_tieba_crawler
  • 百度小程序遇到的问题
  • 给github项目添加CI badge
  • 看完九篇字体系列的文章,你还觉得我是在说字体?
  • 前端学习笔记之观察者模式
  • 前端学习笔记之原型——一张图说明`prototype`和`__proto__`的区别
  • 使用 @font-face
  • 小而合理的前端理论:rscss和rsjs
  • Spring第一个helloWorld
  • 阿里云服务器购买完整流程
  • 东超科技获得千万级Pre-A轮融资,投资方为中科创星 ...
  • ​​​​​​​STM32通过SPI硬件读写W25Q64
  • ​ArcGIS Pro 如何批量删除字段
  • ​Benvista PhotoZoom Pro 9.0.4新功能介绍
  • #07【面试问题整理】嵌入式软件工程师
  • #Js篇:单线程模式同步任务异步任务任务队列事件循环setTimeout() setInterval()
  • #绘制圆心_R语言——绘制一个诚意满满的圆 祝你2021圆圆满满
  • (Redis使用系列) SpirngBoot中关于Redis的值的各种方式的存储与取出 三
  • (带教程)商业版SEO关键词按天计费系统:关键词排名优化、代理服务、手机自适应及搭建教程