不小心写死循环窗口弹出了
发布时间:
更新时间:
🕒 阅读时间:6 min read
👀 阅读量:Loading...
关键代码
// 定义一个响应式的引用,用于笔记的文本内容const textcontent = ref('');
// 导入必要的Vue组合API函数和Tauri APIimport { ref, onMounted, onUnmounted } from 'vue';import { Window } from '@tauri-apps/api/window';import { invoke } from '@tauri-apps/api/core';
// 从Tauri获取当前窗口实例const currentWindow = Window.getCurrent();
// 用于保存清理函数的变量let unlisten: (() => void) | undefined;
// 组件挂载时运行的生命周期钩子onMounted(async () => { // 监听窗口关闭请求事件 unlisten = await currentWindow.onCloseRequested(async (event) => { // 阻止默认关闭行为,以便手动处理 event.preventDefault(); // 调用后端命令保存笔记,传递窗口标签和内容 const shouldClose = await invoke('save_notes', { label: currentWindow.label, content: textcontent.value, }); // 如果后端指示关闭,则销毁窗口 if (shouldClose) { currentWindow.destroy(); } });});
// 组件卸载时运行的生命周期钩子onUnmounted(() => { // 如果存在,清理事件监听器 if (unlisten) { unlisten(); }});
// 导入必要的Tauri模块,用于处理应用和窗口管理use tauri::{AppHandle, Manager};// 从Tauri对话框插件导入对话框扩展和按钮类型use tauri_plugin_dialog::{DialogExt, MessageDialogButtons};
// 定义一个可以从前端调用的Tauri命令// 此命令接受窗口标签、笔记内容和应用句柄作为参数#[tauri::command]pub fn save_notes(label: &str, content: &str, app: AppHandle) { // 打印调试消息,指示特定窗口的保存操作 println!("nia - saving note for window: {}", label);
// 检索与给定标签关联的webview窗口 // 这会解包Option,假设窗口存在(在生产中,应正确处理错误) let note_window = app.get_webview_window(label).unwrap();
// 克隆窗口句柄以在闭包中使用,避免所有权问题 let note_window_clone = note_window.clone();
// 在窗口上构建并显示消息对话框 // 对话框询问用户是否要保存笔记 let result = note_window .dialog() .message("Do you want to save the note?") // 对话框中显示的消息 .title("Save Note") // 对话框窗口的标题 .buttons(MessageDialogButtons::OkCancelCustom( "Save".to_string(), // 确定按钮的自定义文本 "Cancel".to_string(), // 取消按钮的自定义文本 )) // 显示对话框并异步处理结果 .show(move |result| match result { // 如果用户点击“保存”(true) true => { // 打印结果用于调试 println!("{}", result); // 尝试关闭窗口;使用let _忽略任何错误 let _ = note_window_clone.close(); } // 如果用户点击“取消”(false) false => { let _ = note_window_clone.close(); } });}
这真是让我自己气笑了——不小心写了个死循环,导致窗口不停弹出对话框,每次都问要不要保存,但无论选什么都会关闭窗口,又触发关闭事件,循环往复。
修正
const textcontent = ref('');import { ref, onMounted, onUnmounted } from 'vue';import { Window } from '@tauri-apps/api/window';import { invoke } from '@tauri-apps/api/core';import { listen } from '@tauri-apps/api/event';interface Event { payload: boolean;}const currentWindow = Window.getCurrent();let unlisten: (() => void) | undefined;let unlistenNoteClose: (() => void) | undefined;let ifclose = ref<boolean>(false);onMounted(async () => { unlistenNoteClose = await listen('note_close', (event: Event) => { ifclose.value = event.payload; console.log('saiodiojas ' + ifclose.value); }); unlisten = await currentWindow.onCloseRequested(async (event) => { if (!ifclose.value) { event.preventDefault(); const shouldClose = await invoke('save_notes', { label: currentWindow.label, content: textcontent.value, }); } });});
use tauri::{AppHandle, Emitter, Manager};use tauri_plugin_dialog::{DialogExt, MessageDialogButtons};#[tauri::command]
pub fn save_notes(label: &str, content: &str, app: AppHandle) { println!("nia - saving note for window: {}", label); let note_window = app.get_webview_window(label).unwrap(); let note_window_clone = note_window.clone(); let app_clone = app.clone(); let label_clone = label.to_string(); let result = note_window .dialog() .message("Do you want to save the note?") .title("Save Note") .buttons(MessageDialogButtons::OkCancelCustom( "Save".to_string(), "Cancel".to_string(), )) .show(move |result| match result { true => { println!("{}", result); app_clone .emit_to(&label_clone, "note_close", result) .unwrap();
let _ = note_window_clone.close(); } // do something, false => { let _ = note_window_clone.close(); } // do something, });}
-
前端修正:添加了监听
note_close
事件的逻辑,使用ifclose
标志来控制是否阻止窗口关闭请求。只有在未收到关闭信号时才阻止默认关闭行为并调用后端保存逻辑,避免了无限循环。 -
后端修正:在用户选择保存时,通过
emit_to
发送事件到前端,设置关闭标志,然后关闭窗口。而在取消时直接关闭窗口,不发送事件,确保不会重复触发关闭请求。 -
整体效果:这修复了死循环问题,现在保存时窗口正常关闭,取消时也直接关闭,不会反复弹出对话框。😄
不小心写死循环窗口弹出了
本文链接: https://xingwangzhe.fun/posts/505f6391
本文采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。
留言评论