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

2024-08-27 16:20

本文主要是介绍【一起学Rust | 框架篇 | Tauri2.0框架】rust和前端的相互调用(前端调用rust),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在这里插入图片描述

文章目录

    • 前言
    • 1. 前端调用rust(command)
      • 1. 在后端定义一个`command`
      • 2. 注册`command`
      • 3. 前端调用`command`
    • 2. 前端调用rust(event)
    • 4. command完整实例


前言

本期将继续接着上一期,继续探索tauri中rust和前端的相互调用,上一期我们介绍了rust调用前端,这一期我们继续探索前端调用rust。

首先还是回忆一下上周tauri的前后端通信示意图

tauri事件机制

从该图片我们可以清晰的看出来,tauri的前端和rust后端通信是通过事件机制来实现的,在上期中,我介绍了事件机制的基础,以及如何通过rust的工具来调用前端的方法,也就是触发前端监听的事件。

这张图是双向的,也就是说前端也可以触发rust监听的事件,这样前端也可以调用rust的方法,这也是本期的主要内容。

除此以外,tauri官方推荐的前端调用rust后端的主要方法是通过command来调用,因此,如果你要做的东西比较简单,那么更建议使用command来调用,因为command的调用方式更简单,更符合前端开发者的习惯,而且选择合适的使用场景的能力对于一个开发人员来说也是非常重要的。

Command通信示意图

从图上可以看出,tauri的command其实与fetch api是非常相似的,都是请求、响应的模式,但其实这个机制是使用json-rpc来实现的(这些都是官方写的),不过这个不需要深究,除非你是老专家。我们只需要知道怎么用的,置于原理那是后面的事情,如果tauri可以活到那个时候的话。

以上是tauri使用command来与rust后端通信的流程图。其中一些转换方法tauri已经为我们实现了,当你理解了这张图,在使用command时就会非常简单。

Because this mechanism uses a JSON-RPC like protocol under the hood to serialize requests and responses, all arguments and return data must be serializable to JSON.

注意:本文内容均可在官方文档中找到对应内容: https://v2.tauri.app/concept/inter-process-communication/

1. 前端调用rust(command)

为了更加方便的描述tauri是如何从前端调用rust的,我先写一个流程,然后以这个流程来逐步实现该功能。

  1. 在rust后端定义一个command
  2. 注册command
  3. 前端调用command

1. 在后端定义一个command

在rust中,command的定义非常简单,只需要在src-tauri/src/main.rs中定义一个函数,并使用tauri::command!宏来标记该函数为command即可,就像程序自带的command,greet就是这么做的(学习就是在看例子)。

#[tauri::command]
fn greet(name: &str) -> String {format!("Hello, {}! You've been greeted from Rust!", name)
}

在这个greet的例子中,可以看到,name是需要传入的参数,然后返回一个格式化的字符串。(不写分号等于返回,不需要写return)
那么在这里需要注意的是参数,也就是tauri如何接受参数,根据官方文档,传入参数可以是任意类型,但是前提是这个类型必须实现serde::Deserialize

注意:参数是可以重命名的,类似于后端开发中的dto,但是需要使用#[tauri::command(rename_all = "snake_case")]来标记,否则tauri会报错。这样前端就可以传入与后端参数名一样了。

返回值必须是String,因为要序列化(其实可以返回任何类型,但是你的类型必须实现serde::Serialize,如果是传入参数,那么必须实现serde::Deserialize,个人建议这两个序列化和反序列化的特征全部实现,就不用考虑那么多了,如果你比较仔细,就可以在这仔细看看)。

初次以外还可以返回数组buffer,可以用(tauri::ipc::Response),错误处理也可使用Result,本文章不可能做到面面俱到,读者应学会看官方文档,当然在后续文章中我应该也是会补上的。

注意:

  1. 其实你也可以把command放在lib.rs,拆分开这样代码才会更加条理。
  2. command是唯一的,不允许重复,也就是说,你得注意命名规范,避免重复。

2. 注册command

在定义完command之后,我们需要将command注册到tauri中,这样tauri才能知道我们定义了哪些command,前端才能调用这些command

src-tauri/src/main.rs中,我们可以看到tauri::Builder的实例,我们可以在这个实例上调用invoke_handler方法来注册command

tauri::Builder::default().invoke_handler(tauri::generate_handler![greet])

这是官方案例中的greet方法,我们只需要学习其使用方法就可以了,可以直接跟在greet后面(那是个数组),或者替换也没关系,就像下面这样

tauri::Builder::default().invoke_handler(tauri::generate_handler![greet, another_command])

这样就可以注册多个command了。

3. 前端调用command

在tauri 2.0中,tauri导出了invoke方法,因此我们导入该方法以后调用即可。

// 导入 invoke 方法
import { invoke } from '@tauri-apps/api/core';// ...
invoke('my_custom_command'); //调用 command

注意:tauri官方推荐使用异步command,但是经我自己测试是有问题的,异步command执行不了异步方法(笑死)。

2. 前端调用rust(event)

使用事件来进行通信与上期内容是差不多的。在前端中,tauri导出了emit方法,我们导入这个方法就可以触发rust中的监听器。

// 导入 emit 方法
import { emit } from '@tauri-apps/api/event';// ...
emit('my_custom_event', payload); //触发事件

其中,payload是传递给rust的参数,是个对象。

然后在rust中监听这个事件

use tauri::Listener;#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {tauri::Builder::default().setup(|app| {app.listen("my_custom_event", |event| {if let Ok(payload) = serde_json::from_str::<DownloadStarted>(&event.data) {println!("downloading {}", payload.url);}});Ok(())}).run(tauri::generate_context!()).expect("error while running tauri application");
}

注意:你甚至可以用前端监听事件,触发事件,简直非常好用。

发挥你的想象力,如果你想要监听指定webview的事件,那么也是可以实现的

use tauri::{Listener, Manager};#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {tauri::Builder::default().setup(|app| {let webview = app.get_webview_window("main").unwrap();webview.listen("logged-in", |event| {let session_token = event.data;// save token..});Ok(())}).run(tauri::generate_context!()).expect("error while running tauri application");
}

官方文档内容非常多,如果看完这些你还存在问题,那么请看官方文档,或者者在下方留言。

4. command完整实例

在rust中定义command

struct Database;#[derive(serde::Serialize)]
struct CustomResponse {message: String,other_val: usize,
}async fn some_other_function() -> Option<String> {Some("response".into())
}#[tauri::command]
async fn my_custom_command(window: tauri::Window,number: usize,database: tauri::State<'_, Database>,
) -> Result<CustomResponse, String> {println!("Called from {}", window.label());let result: Option<String> = some_other_function().await;if let Some(message) = result {Ok(CustomResponse {message,other_val: 42 + number,})} else {Err("No result".into())}
}#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {tauri::Builder::default().manage(Database {}).invoke_handler(tauri::generate_handler![my_custom_command]).run(tauri::generate_context!()).expect("error while running tauri application");
}

然后在前端中调用

import { invoke } from '@tauri-apps/api/core';// Invocation from JavaScript
invoke('my_custom_command', {number: 42,
}).then((res) =>console.log(`Message: ${res.message}, Other Val: ${res.other_val}`)).catch((e) => console.error(e));

这篇关于【一起学Rust | 框架篇 | Tauri2.0框架】rust和前端的相互调用(前端调用rust)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1112168

相关文章

Java中调用数据库存储过程的示例代码

《Java中调用数据库存储过程的示例代码》本文介绍Java通过JDBC调用数据库存储过程的方法,涵盖参数类型、执行步骤及数据库差异,需注意异常处理与资源管理,以优化性能并实现复杂业务逻辑,感兴趣的朋友... 目录一、存储过程概述二、Java调用存储过程的基本javascript步骤三、Java调用存储过程示

Spring 框架之Springfox使用详解

《Spring框架之Springfox使用详解》Springfox是Spring框架的API文档工具,集成Swagger规范,自动生成文档并支持多语言/版本,模块化设计便于扩展,但存在版本兼容性、性... 目录核心功能工作原理模块化设计使用示例注意事项优缺点优点缺点总结适用场景建议总结Springfox 是

Python中Tensorflow无法调用GPU问题的解决方法

《Python中Tensorflow无法调用GPU问题的解决方法》文章详解如何解决TensorFlow在Windows无法识别GPU的问题,需降级至2.10版本,安装匹配CUDA11.2和cuDNN... 当用以下代码查看GPU数量时,gpuspython返回的是一个空列表,说明tensorflow没有找到

python如何调用java的jar包

《python如何调用java的jar包》这篇文章主要为大家详细介绍了python如何调用java的jar包,文中的示例代码简洁易懂,具有一定的借鉴价值,有需要的小伙伴可以参考一下... 目录一、安装包二、使用步骤三、代码演示四、自己写一个jar包五、打包步骤六、方法补充一、安装包pip3 install

前端如何通过nginx访问本地端口

《前端如何通过nginx访问本地端口》:本文主要介绍前端如何通过nginx访问本地端口的问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、nginx安装1、下载(1)下载地址(2)系统选择(3)版本选择2、安装部署(1)解压(2)配置文件修改(3)启动(4)

HTML中meta标签的常见使用案例(示例详解)

《HTML中meta标签的常见使用案例(示例详解)》HTMLmeta标签用于提供文档元数据,涵盖字符编码、SEO优化、社交媒体集成、移动设备适配、浏览器控制及安全隐私设置,优化页面显示与搜索引擎索引... 目录html中meta标签的常见使用案例一、基础功能二、搜索引擎优化(seo)三、社交媒体集成四、移动

HTML input 标签示例详解

《HTMLinput标签示例详解》input标签主要用于接收用户的输入,随type属性值的不同,变换其具体功能,本文通过实例图文并茂的形式给大家介绍HTMLinput标签,感兴趣的朋友一... 目录通用属性输入框单行文本输入框 text密码输入框 password数字输入框 number电子邮件输入编程框

HTML img标签和超链接标签详细介绍

《HTMLimg标签和超链接标签详细介绍》:本文主要介绍了HTML中img标签的使用,包括src属性(指定图片路径)、相对/绝对路径区别、alt替代文本、title提示、宽高控制及边框设置等,详细内容请阅读本文,希望能对你有所帮助... 目录img 标签src 属性alt 属性title 属性width/h

CSS3打造的现代交互式登录界面详细实现过程

《CSS3打造的现代交互式登录界面详细实现过程》本文介绍CSS3和jQuery在登录界面设计中的应用,涵盖动画、选择器、自定义字体及盒模型技术,提升界面美观与交互性,同时优化性能和可访问性,感兴趣的朋... 目录1. css3用户登录界面设计概述1.1 用户界面设计的重要性1.2 CSS3的新特性与优势1.

Python的端到端测试框架SeleniumBase使用解读

《Python的端到端测试框架SeleniumBase使用解读》:本文主要介绍Python的端到端测试框架SeleniumBase使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全... 目录SeleniumBase详细介绍及用法指南什么是 SeleniumBase?SeleniumBase