【Tauri2.0教程(十一)】让APP关联文件格式右键打开

说明

APP右键打开文件,即如下图所示: 当鼠标在相应文件(比如图片)上面右键的时候,可以在打开方式中关联到我们自己开发的应用,进一步也可以将该程序设置为默认打开程序,但是后者是操作系统的行为,这里不赘述。本文主要讲如何将使用tauri开发的APP关联到对应格式的文件上面,使得在文件上右键的时候能够找到我们开发的应用程序。

配置

tauri.conf.json文件中添加如下配置,其中ext为必填项,表示为哪些格式的文件添加右键打开方式,description表示右键菜单显示什么名称。还有其他一些可选配置,这里不做介绍,需要可以自行查阅官方文档

json 复制代码
"bundle":{
    "fileAssociations": [
      {
        "description": "sharpify",
        "ext": [
          "jpg",
          "jpeg",
          "png"
        ]
      }
    ]
}

上述配置完成以后,将程序进行打包,在jpg、jpeg、png三种图片格式的文件上右键以后,就可以看到已经能够关联我们开发的APP了。

但是还没结束。

虽然已经关联右键菜单了,但是触发右键菜单的行为现在还没有需要我们自己实现。

实现逻辑比较简单,在后端main函数,tauri构建的时候,在setup()函数里面可以得到需要打开的文件全路径,代码如下:

rust 复制代码
fn main() {
    tauri::Builder::default()
        .setup(|app| {
            let args: Vec<String> = std::env::args().collect();
            for arg in args {
                if arg.ends_with(".jpg") || arg.ends_with(".png") {
                    // 我们右键文件的路径名称
                    println!(arg)
                }
            }
            Ok(())
        })
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

如果需要将文件在前端展示的话,就需要涉及跟前端交互的动作,总体来说有两种思路:

  • 当后端(rust)获取图片以后,使用app.emit('open-image', arg)的方式,向前端(vue)发送信息,前端监听该事件
  • 后端获取到要打开的文件路径以后,先存储起来,等前端就绪以后,主动调用后端获取需要的内容

思路一

第一种思路看起来更合理一些,拿到结果以后,主动向前端推送。但是有个问题,这种推送-监听的方式容易丢失数据,比如如果后端先准备好了,他使用emit推送数据了,但是前端并没有准备好,等准备好以后再listen,这时候数据已经不存在了,就无法监听到了。

部分代码如下:

rust 复制代码
fn main() {
    tauri::Builder::default()
        .setup(|app| {
            // 将路径传给前端 Vue 
            log::info!("emit args:{}", &arg); 
                match window.emit_str("open-image", arg) { 
                Ok(_) => log::info!("arg emit successful "), 
                Err(e) => log::error!("something wrong {}", e) 
            }
            Ok(())
        })
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}
js 复制代码
onMounted(async () => {
 // 前端通过listen监听后端数据
  fileAssociationUnListen = await listen("open-image", event => {
    filePath.value = event.payload;
    console.log("11111", filePath)
    setTimeout(()=>{
      info("-----image:" + filePath)
    }, 10*1000)
    info('image 文件路径:{}' + filePath);
  });
})

上述代码看起来比较合理,但是如果后端加载先于前端,就会导致前端拿不到数据,事实经过测试也确实是这样的。

思路二

后端拿到数据以后将文件路径存储起来,当前端就绪以后,主动调用后端方法,获取文件路径,然后进行显示:

rust 复制代码
use tauri::{Manager, State};
use std::sync::Mutex;

#[derive(Default)]
struct StartupImagePath(Mutex<Option<String>>);

#[tauri::command]
fn get_startup_image_path(state: State<StartupImagePath>) -> Option<String> {
    state.0.lock().unwrap().clone()
}

fn main() {
    tauri::Builder::default()
        .manage(StartupImagePath::default()) // ✅ 注册状态
        .setup(|app| {
            let args: Vec<String> = std::env::args().collect();
            for arg in args {
                if arg.ends_with(".jpg") || arg.ends_with(".png") {
                    app.state::<StartupImagePath>()
                        .0
                        .lock()
                        .unwrap()
                        .replace(arg);
                }
            }
            Ok(())
        })
        .invoke_handler(tauri::generate_handler![get_startup_image_path])
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}
js 复制代码
invoke('get_startup_image_path').then(path => {
  if (path){
    console.log("path=", path)
    filePath.value = path
    info("path" + path);
  }
})

上述代码可以实现我们的需求,但是有一个潜在问题:我们希望右键文件打开app的时候能够触发这套逻辑,但是如果这么写的话,正常双击app图标打开也会调用完整的代码。

总结

本文主要描述了如何为tauri开发的app关联右键菜单。以后关联后如何触发后续软件的行为。 同时介绍了一种比较特殊的情况:当需要将后端数据传递给前端的时候,采用什么方式比较有效。但是仍然存在一定的问题。如果各位有更好的方式、欢迎留言。

相关推荐
xd000024 小时前
2.从0开始搭建vue项目(node.js,vue3,Ts,ES6)
vue.js·node.js
赵大仁5 小时前
深入理解 Pinia:Vue 状态管理的革新与实践
前端·javascript·vue.js
前端大卫8 小时前
Vue3 里的 h 函数的运用场景!
前端·vue.js
慌糖9 小时前
Vue组件化
前端·javascript·vue.js
blues_C9 小时前
十一、【核心功能篇】测试用例管理:设计用例新增&编辑界面
前端·vue.js·测试用例·element plus·测试平台
Y学院10 小时前
Vue 技术文档
vue.js·笔记·学习
JuneXcy13 小时前
Vue 核心技术与实战day07
前端·javascript·vue.js
前端工作日常13 小时前
我理解的Vue样式穿透
vue.js
海天胜景14 小时前
vue3 el-input type=“textarea“ 字体样式 及高度设置
javascript·vue.js·elementui