【一起学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

相关文章

前端原生js实现拖拽排课效果实例

《前端原生js实现拖拽排课效果实例》:本文主要介绍如何实现一个简单的课程表拖拽功能,通过HTML、CSS和JavaScript的配合,我们实现了课程项的拖拽、放置和显示功能,文中通过实例代码介绍的... 目录1. 效果展示2. 效果分析2.1 关键点2.2 实现方法3. 代码实现3.1 html部分3.2

Deepseek R1模型本地化部署+API接口调用详细教程(释放AI生产力)

《DeepseekR1模型本地化部署+API接口调用详细教程(释放AI生产力)》本文介绍了本地部署DeepSeekR1模型和通过API调用将其集成到VSCode中的过程,作者详细步骤展示了如何下载和... 目录前言一、deepseek R1模型与chatGPT o1系列模型对比二、本地部署步骤1.安装oll

CSS弹性布局常用设置方式

《CSS弹性布局常用设置方式》文章总结了CSS布局与样式的常用属性和技巧,包括视口单位、弹性盒子布局、浮动元素、背景和边框样式、文本和阴影效果、溢出隐藏、定位以及背景渐变等,通过这些技巧,可以实现复杂... 一、单位元素vm 1vm 为视口的1%vh 视口高的1%vmin 参照长边vmax 参照长边re

一分钟带你上手Python调用DeepSeek的API

《一分钟带你上手Python调用DeepSeek的API》最近DeepSeek非常火,作为一枚对前言技术非常关注的程序员来说,自然都想对接DeepSeek的API来体验一把,下面小编就来为大家介绍一下... 目录前言免费体验API-Key申请首次调用API基本概念最小单元推理模型智能体自定义界面总结前言最

修改若依框架Token的过期时间问题

《修改若依框架Token的过期时间问题》本文介绍了如何修改若依框架中Token的过期时间,通过修改`application.yml`文件中的配置来实现,默认单位为分钟,希望此经验对大家有所帮助,也欢迎... 目录修改若依框架Token的过期时间修改Token的过期时间关闭Token的过期时js间总结修改若依

CSS3中使用flex和grid实现等高元素布局的示例代码

《CSS3中使用flex和grid实现等高元素布局的示例代码》:本文主要介绍了使用CSS3中的Flexbox和Grid布局实现等高元素布局的方法,通过简单的两列实现、每行放置3列以及全部代码的展示,展示了这两种布局方式的实现细节和效果,详细内容请阅读本文,希望能对你有所帮助... 过往的实现方法是使用浮动加

css渐变色背景|<gradient示例详解

《css渐变色背景|<gradient示例详解》CSS渐变是一种从一种颜色平滑过渡到另一种颜色的效果,可以作为元素的背景,它包括线性渐变、径向渐变和锥形渐变,本文介绍css渐变色背景|<gradien... 使用渐变色作为背景可以直接将渐China编程变色用作元素的背景,可以看做是一种特殊的背景图片。(是作为背

JAVA调用Deepseek的api完成基本对话简单代码示例

《JAVA调用Deepseek的api完成基本对话简单代码示例》:本文主要介绍JAVA调用Deepseek的api完成基本对话的相关资料,文中详细讲解了如何获取DeepSeekAPI密钥、添加H... 获取API密钥首先,从DeepSeek平台获取API密钥,用于身份验证。添加HTTP客户端依赖使用Jav

在Rust中要用Struct和Enum组织数据的原因解析

《在Rust中要用Struct和Enum组织数据的原因解析》在Rust中,Struct和Enum是组织数据的核心工具,Struct用于将相关字段封装为单一实体,便于管理和扩展,Enum用于明确定义所有... 目录为什么在Rust中要用Struct和Enum组织数据?一、使用struct组织数据:将相关字段绑

CSS自定义浏览器滚动条样式完整代码

《CSS自定义浏览器滚动条样式完整代码》:本文主要介绍了如何使用CSS自定义浏览器滚动条的样式,包括隐藏滚动条的角落、设置滚动条的基本样式、轨道样式和滑块样式,并提供了完整的CSS代码示例,通过这些技巧,你可以为你的网站添加个性化的滚动条样式,从而提升用户体验,详细内容请阅读本文,希望能对你有所帮助...