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

news2024/9/22 4:25:28

在这里插入图片描述

文章目录

    • 前言
    • 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 listeners
    app.emit_to(EventTarget::any(), "download-progress", i);
    // emit an event to listeners that used App::listen or AppHandle::listen
    app.emit_to(EventTarget::app(), "download-progress", i);
    // emit an event to any webview/window/webviewWindow matching the given label
    app.emit_to("updater", "download-progress", i); // similar to using EventTarget::labeled
    app.emit_to(EventTarget::labeled("updater"), "download-progress", i);
    // emit an event to listeners that used WebviewWindow::listen
    app.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 window
    app.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,这个内容放到下期。(你英文好的话也可以直接看官方文档。)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2057526.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Redis7基础篇(六)

redis复制 目录 redis复制 前引 概念 能干嘛 怎么玩 基本操作 案例演示 前期配置 实操 常用三招 一主二仆 薪火相传 反客为主 复制原理和工作流程 复制的缺点 前引 redis复制这一篇有承上启下的作用 前面的 redis几乎是单机版 一台redis 概念 能干嘛 水平扩容…

收银系统源码-购物卡与会员卡的区别

很多门店都会推出一些只有指定商品才可以使用的购物卡或不同额度、不同折扣的消费卡&#xff0c;用来进行一些商品的促销或会员储值。如今时代实体卡容易丢失&#xff0c;很多人出门不愿意带钱包卡包。如果您有这样的功能需求&#xff0c;快来看看千呼新零售2.0购物卡功能吧&am…

[FSCTF 2023]寻找蛛丝马迹

点一下&#xff0c;看到只有页面背景颜色变化 查看一下页面源码吧&#xff0c;发现第一段flag 访问一下styles.css,看到顶部有一串乱码&#xff08;应该是flag一部分&#xff09;我们用火狐的修复文字编码工具 进行修复后显示 然后再访问script.js,依旧是乱码&#xff0c;同样…

数据湖之Delta Lake

Delta Lake&#xff1a;数据湖存储层概述 Delta Lake 是一种开源的存储层技术&#xff0c;构建在 Apache Spark 的基础之上&#xff0c;旨在解决传统数据湖的可靠性、性能和数据一致性问题。它通过引入 ACID 事务、数据版本控制、时间旅行和统一的批处理与流处理等特性&#x…

【SCI/EI/SCOPUS/CNKI】第三届先进材料与装备制造国际会议(AMEM2024)

会议日期&#xff1a;2024年12月28-30日 会议地点&#xff1a;中国-云南省-昆明市 会议官网&#xff1a;https://www.iaast.cn/meet/home/Bx93wRT 出版检索&#xff1a;EI、Scopus等数据库收录 【主办单位】 国际应用科学与技术协会(IAAST) 【主讲嘉宾】 【论文出版与检…

20 数据可视化

20 数据可视化 本章概述一. `elasticsearch`实现数据统计1.1 创建用户信息索引1.1.1 控制台创建`aggs_user`索引1.1.2 `aggs_user`索引结构初始化1.1.3 创建`aggs_user`索引的`EO`对象1.1.4 用户类型枚举1.1.5 数据初始化****************************************************…

引入本地iconfont图标

iconfont-阿里巴巴图标库官网&#xff0c;搜索想要的图标 1、加入购物车 2、添加至项目 头部的资源管理&#xff0c;点我的项目 找到对应的项目&#xff0c;点击 下载至本地&#xff0c;是个zip压缩包 解压缩一下&#xff0c;copy一下文件&#xff0c;放到项目里&#xff0c;…

打印空心正方形(c语言)

1.//KiKi学习了循环&#xff0c;BoBo老师给他出了一系列打印图案的练习&#xff0c;该任务是打印用“* ”组成的“空心”正方形图案。 //输入描述 : //多组输入&#xff0c;一个整数&#xff08;3~20&#xff09;&#xff0c;表示输出的行数&#xff0c;也表示组成正方形边的“…

PCBlayout什么意思

PCB (Printed Circuit Board) layout 是指在设计印制电路板的过程中&#xff0c;对电子元器件及导电路径进行合理布置的过程。这个过程对于确保电路板的功能性和可靠性至关重要。下面是一些 PCB layout 的基本概念和步骤&#xff1a; 元件放置&#xff1a; 元件放置是 PCB 设计…

AI在线免费数学工具:Qwen2-Math

1、Qwen2-Math https://huggingface.co/spaces/Qwen/Qwen2-Math-Demo

python中使用gurobi遇到强不等式约束(只有大于或者小于而不是大于等于或者小于等于的形式)的解决办法

文章目录 情况分析与解决思路数学模型严格不等式约束转化后的约束形式带入具体的 ϵ \epsilon ϵ 值 python代码总结 情况分析与解决思路 在gurobi求解数学优化问题时&#xff0c;标准的约束形式通常是大于等于&#xff08; >&#xff09;或小于等于&#xff08;<&…

nginx简介及功能介绍

目录 niginx与apache niginx特点 nginx模块介绍 nginx的编译安装 nginx的平滑升级及版本回滚 niginx的常用参数 nginx独立文件编写 location匹配用法 自定义日志 文件检测 nginx中的长链接管理 nginx下载服务器设置 nginx的状态页面 nginx的数据压缩功能 nginx的…

客车制造5G智能工厂工业物联数字孪生平台,推进制造业数字化转型

制造业正经历着前所未有的变革&#xff0c;其中客车制造行业作为传统制造业的重要组成部分&#xff0c;正积极拥抱5G、工业物联网及数字孪生等先进技术&#xff0c;推动生产模式的全面升级与数字化转型。 客车制造5G智能工厂工业物联数字孪生平台的出现&#xff0c;不仅为行业…

Datawhale X 魔搭 AI夏令营-大模型技术(微调)-大模型评分

大语言模型&#xff08;LLMs&#xff09;在自动化复杂评分任务和增强决策过程方面展示了巨大的潜力。从作文评分到信用风险评估&#xff0c;LLMs 已表现出卓越的文本理解和分析能力。然而&#xff0c;要充分利用LLMs的潜力&#xff0c;必须探索如何将它们与其他AI形式&#xff…

Python数据分析项目实战01_票房榜单分析和pyecharts大屏可视化

一&#xff1a;最终大屏效果展示 由于生成了html网页只能在本地上显示&#xff0c;这个大屏是动态的&#xff0c;只能显示其中的图片。如果要分享给他人使用&#xff0c;就需要将html源码转为网页。 生成的html源码入口&#xff1a;‬​‍​‌‌​⁠​​​‌‍​​​​​‬&a…

百日筑基第五十七天-虚拟线程

百日筑基第五十七天-虚拟线程 前提 JDK19于2022-09-20发布GA版本&#xff0c;该版本提供了虚拟线程的预览功能。下载JDK19之后翻看了一下有关虚拟线程的一些源码&#xff0c;跟早些时候的Loom项目构建版本基本并没有很大出入&#xff0c;也跟第三方JDK如鹅厂的Kona虚拟线程实…

Leetcode JAVA刷刷站(58)最后一个单词的长度

一、题目概述 二、思路方向 要解决这个问题&#xff0c;你可以通过遍历字符串 s 并从后往前计数的方式来实现。但更简洁且易于理解的方法是&#xff0c;首先去除字符串尾部的空格&#xff08;如果有的话&#xff09;&#xff0c;然后找到最后一个单词的起始位置&#xff0c;并计…

I2C学习:传输速率

一&#xff0e;内容简介 I2C总线根据传输速度不同&#xff0c;可以划分为5种速度模式&#xff0c;见下列表格。 速度模式 最高速率 备注 标准模式Sm 100Kbps 双向传输 向下兼容 快速模式Fm 400Kbps 快速模式增强Fm 1Mbps 高速模式HSm 3.4Mbps 超快速模式UFm 5Mbp…

解决在移动端css使用100vh底部被遮盖的问题

原文引用&#xff1a;https://blog.csdn.net/hw_happy/article/details/132421653 移动端下&#xff0c;若使用100vh单位&#xff0c;那么高度不会是浏览器可视区域的高度&#xff0c;而是会高于可视区域&#xff0c;所以居底部的元素会被遮盖住&#xff1a; 如果是chrome浏览…

autocommit自动提交事务及commit、rollback用法

MySQL默认开启事务自动提交&#xff0c;每条SQL语句都会被当做一个单独的事务自动执行。 一、查看autocommit自动提交事物状态 SHOW VARIABLES LIKE ‘autocommit’; 1、开启状态&#xff1a;ON autocommit的值为ON&#xff0c;表示系统开启自动提交模式 2、关闭状态&#…