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

相关文章

HTML5中的Microdata与历史记录管理详解

《HTML5中的Microdata与历史记录管理详解》Microdata作为HTML5新增的一个特性,它允许开发者在HTML文档中添加更多的语义信息,以便于搜索引擎和浏览器更好地理解页面内容,本文将探... 目录html5中的Mijscrodata与历史记录管理背景简介html5中的Microdata使用M

html5的响应式布局的方法示例详解

《html5的响应式布局的方法示例详解》:本文主要介绍了HTML5中使用媒体查询和Flexbox进行响应式布局的方法,简要介绍了CSSGrid布局的基础知识和如何实现自动换行的网格布局,详细内容请阅读本文,希望能对你有所帮助... 一 使用媒体查询响应式布局        使用的参数@media这是常用的

HTML5表格语法格式详解

《HTML5表格语法格式详解》在HTML语法中,表格主要通过table、tr和td3个标签构成,本文通过实例代码讲解HTML5表格语法格式,感兴趣的朋友一起看看吧... 目录一、表格1.表格语法格式2.表格属性 3.例子二、不规则表格1.跨行2.跨列3.例子一、表格在html语法中,表格主要通过< tab

Vue3组件中getCurrentInstance()获取App实例,但是返回null的解决方案

《Vue3组件中getCurrentInstance()获取App实例,但是返回null的解决方案》:本文主要介绍Vue3组件中getCurrentInstance()获取App实例,但是返回nu... 目录vue3组件中getCurrentInstajavascriptnce()获取App实例,但是返回n

JS+HTML实现在线图片水印添加工具

《JS+HTML实现在线图片水印添加工具》在社交媒体和内容创作日益频繁的今天,如何保护原创内容、展示品牌身份成了一个不得不面对的问题,本文将实现一个完全基于HTML+CSS构建的现代化图片水印在线工具... 目录概述功能亮点使用方法技术解析延伸思考运行效果项目源码下载总结概述在社交媒体和内容创作日益频繁的

前端CSS Grid 布局示例详解

《前端CSSGrid布局示例详解》CSSGrid是一种二维布局系统,可以同时控制行和列,相比Flex(一维布局),更适合用在整体页面布局或复杂模块结构中,:本文主要介绍前端CSSGri... 目录css Grid 布局详解(通俗易懂版)一、概述二、基础概念三、创建 Grid 容器四、定义网格行和列五、设置行

前端下载文件时如何后端返回的文件流一些常见方法

《前端下载文件时如何后端返回的文件流一些常见方法》:本文主要介绍前端下载文件时如何后端返回的文件流一些常见方法,包括使用Blob和URL.createObjectURL创建下载链接,以及处理带有C... 目录1. 使用 Blob 和 URL.createObjectURL 创建下载链接例子:使用 Blob

Vuex Actions多参数传递的解决方案

《VuexActions多参数传递的解决方案》在Vuex中,actions的设计默认只支持单个参数传递,这有时会限制我们的使用场景,下面我将详细介绍几种处理多参数传递的解决方案,从基础到高级,... 目录一、对象封装法(推荐)二、参数解构法三、柯里化函数法四、Payload 工厂函数五、TypeScript

Java中Date、LocalDate、LocalDateTime、LocalTime、时间戳之间的相互转换代码

《Java中Date、LocalDate、LocalDateTime、LocalTime、时间戳之间的相互转换代码》:本文主要介绍Java中日期时间转换的多种方法,包括将Date转换为LocalD... 目录一、Date转LocalDateTime二、Date转LocalDate三、LocalDateTim

golang获取当前时间、时间戳和时间字符串及它们之间的相互转换方法

《golang获取当前时间、时间戳和时间字符串及它们之间的相互转换方法》:本文主要介绍golang获取当前时间、时间戳和时间字符串及它们之间的相互转换,本文通过实例代码给大家介绍的非常详细,感兴趣... 目录1、获取当前时间2、获取当前时间戳3、获取当前时间的字符串格式4、它们之间的相互转化上篇文章给大家介