目录
前言
这篇就来看看Builder中的方法plugin,主要是用于注册插件。
正文
函数定义
#[must_use]
pub fn plugin<P: Plugin<R> + 'static>(mut self, plugin: P) -> Self {
self.plugins.register(Box::new(plugin));
self
}
需要一个参数plugin,泛型是P,泛型约束是trait Plugin
看看plugins
这是什么?
/// All passed plugins
plugins: PluginStore<R>,
这是一个结构体PluginStore
#[default_runtime(crate::Wry, wry)]
pub(crate) struct PluginStore<R: Runtime> {
store: Vec<Box<dyn Plugin<R>>>,
}
只有一个store字段,是Vec,Vec中的元素类型是Box,Box的泛型约束是dyn Plugin<R>,动态分发的。
看看register方法
pub fn register(&mut self, plugin: Box<dyn Plugin<R>>) -> bool {
let len = self.store.len();
self.store.retain(|p| p.name() != plugin.name());
let result = len != self.store.len();
self.store.push(plugin);
result
}
传入Box,需要满足对应的泛型约束。
先获取Vec的长度,
然后retain函数,过滤存储中的插件
1、保留那些名字不等于新插件名字的插件
2、移除所有同名的旧插件
接着比较过滤前后的长度:
1、如果长度不同,说明移除了旧插件,result 为 true
2、如果长度相同,说明没有旧插件被移除,result 为 false
将插件放到store中,返回result。
说白了,注册插件,就是把Plugin放到Box中,再把Box放到Vec中。
使用plugin函数——Opener
这个插件的作用
This plugin allows you to open files and URLs in a specified, or the default, application. It also supports “revealing” files in the system’s file explorer.
该插件可让您在指定或默认应用程序中打开文件和 URL。它还支持在系统文件资源管理器中 “显示 ”文件。
Tauri的插件还是比较多的。就简单使用Opener插件
Opener | Taurihttps://v2.tauri.app/plugin/opener/在Cargo.toml文件设置依赖
tauri-plugin-opener = "2"
注册
.plugin(tauri_plugin_opener::init())
看看tauri-plugin-opener的init方法
pub fn init<R: Runtime>() -> TauriPlugin<R> {
Builder::default().build()
}
返回TauriPlugin 结构体
可以发现TauriPlugin实现了trait Plugin
impl<R: Runtime, C: DeserializeOwned> Plugin<R> for TauriPlugin<R, C>
没有问题。
简单使用opener
通过记事本读取js文件
项目结构如下
在open.rs中,代码如下
use tauri_plugin_opener::OpenerExt;
use tauri::{command,AppHandle};
#[command]
pub fn open_by_notepad(app: AppHandle) {
let path="./src/test.js";
app.opener().open_path(path, Some("C:/Windows/System32/notepad.exe")).unwrap();
}
导入OpenerExt
这个OpenerExt是个trait
pub trait OpenerExt<R: Runtime>
为tauri::Manager实现了OpenerExt这个trait
impl<R: Runtime, T: Manager<R>> OpenerExt<R> for T
导入了Manager,Apphandle就能使用Manager中的方法
因此Apphandle能使用OpenerExt中的方法。
如果不写这句话,报错如下
error[E0599]: no method named `opener` found for struct `AppHandle` in the current scope
--> src\use_opener\open.rs:5:9
|
5 | app.opener().open_path(path, Some("C:/Windows/System32/notepad.exe")).unwrap();
| ^^^^^^ method not found in `AppHandle`
|
没有这个opener方法。
看看opener方法
fn opener(&self) -> &Opener<R> {
self.state::<Opener<R>>().inner()
}
从state中获取&Opener,看来Opener还是放在state中
既然如此,代码也可写成如下
#[command]
pub fn open_by_notepad(state: State<Opener<Wry>>) {
let path="./src/test.js";
let opener=state.inner();
opener.open_path(path, Some("C:/Windows/System32/notepad.exe")).unwrap();
}
后面的open_path应该就是Opener中的方法。
简单看open_path方法
#[cfg(desktop)]
pub fn open_path(
&self,
path: impl Into<String>,
with: Option<impl Into<String>>,
) -> Result<()>
简单地说
第一个参数&self,不必细说
第二个参数path,传一个能转化成String的的类型,比如说,"abcd"
第三个参数with,传一个Option,Option中泛型是能转化成String的的类型,比如说Some("abc")
返回Result
代码如上所示。
结果
笔者配置许可了默认许可
"opener:default",
注册通信函数并运行,结果如下
如果是使用默认,设参数with为None::<&str>,代码如下
#[command]
pub fn open_by_notepad(app: AppHandle) {
let path="D:\\start\\src-tauri\\src\\test.js";
app.opener().open_path(path, None::<&str>).unwrap();
}
文件的路径要小心。
笔者使用默认的话,笔者是通过WebStorm打开的
打开url
直接给出代码
#[command]
pub fn open_by_url(app: AppHandle) {
let url="https://www.baidu.com";
app.opener().open_url(url,None::<&str>).unwrap();
}
使用默认程序,笔者使用的Edge,自动就打开,没有问题,可以传参,如果有,比如 "firefox"。
需要可能配置权限,后面配置。
在文件夹中显示
#[command]
pub fn show(app: AppHandle) {
app.opener().reveal_item_in_dir("./src/test.js").unwrap();
}
结果成功。
看看函数签名
pub fn reveal_item_in_dir<P: AsRef<Path>>(&self, p: P)
需要一个参数p,对应的泛型约束是AsRef<Path>,任何能转化成Path的类型。
- String
- &str
- PathBuf
- &Path
- 其他实现了 AsRef<Path> 的自定义类型
前端使用opener
打开文件
关键代码如下
import { openPath } from '@tauri-apps/plugin-opener';
async function handleClicked(){
await openPath('D:/start/src-tauri/src/test.js');
}
需要配置许可
{
"identifier": "opener:allow-open-path",
"allow": [
{
"path": "**"
}
]
}
匹配任意路径(包括所有文件和子目录)
运行成功。
使用chrome打开url
笔者默认使用Edge打开,使用chrome的话,需要配置许可
{
"identifier": "opener:allow-open-url",
"allow": [
{
"url": "**",
"app": "chrome"
}
]
}
前端代码如下
async function handleClicked(){
await openUrl("https://github.com","chrome");
}
如果Edge不是默认,想使用Edge,配置为
{
"identifier": "opener:allow-open-url",
"allow": [
{
"url": "**",
"app": "msedge"
}
]
}
也可以指定浏览器的路径,使用Edge Dev版本
{
"identifier": "opener:allow-open-url",
"allow": [
{
"url": "**",
"app":"C:\\Program Files (x86)\\Microsoft\\Edge Dev\\Application\\msedge.exe"
}
]
}
async function handleClicked(){
await openUrl(
"https://github.com",
"C:\\Program Files (x86)\\Microsoft\\Edge Dev\\Application\\msedge.exe");
}
文件显示就不必细说。
看看请求
http://ipc.localhost/plugin%3Aopener%7Copen_path
{path: "D:/start/src-tauri/src/test.js"}
看来本质上是使用了invoke函数
实际上可以发现这样@tauri-apps_plugin-opener.js文件
内容如下
import {
invoke
} from "/node_modules/.vite/deps/chunk-RGZSOVTY.js?v=5f8b5517";
import "/node_modules/.vite/deps/chunk-BUSYA2B4.js?v=5f8b5517";
// node_modules/.pnpm/@tauri-apps+plugin-opener@2.2.6/node_modules/@tauri-apps/plugin-opener/dist-js/index.js
async function openUrl(url, openWith) {
await invoke("plugin:opener|open_url", {
url,
with: openWith
});
}
async function openPath(path, openWith) {
await invoke("plugin:opener|open_path", {
path,
with: openWith
});
}
async function revealItemInDir(path) {
return invoke("plugin:opener|reveal_item_in_dir", { path });
}
export {
openPath,
openUrl,
revealItemInDir
};
//# sourceMappingURL=@tauri-apps_plugin-opener.js.map
看来就是使用了invoke。