不小心写死循环窗口弹出了

发布时间:
更新时间:
🕒 阅读时间:6 min read 👀 阅读量:Loading...

关键代码

关键前端代码
// 定义一个响应式的引用,用于笔记的文本内容
const textcontent = ref('');
// 导入必要的Vue组合API函数和Tauri API
import { 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 发送事件到前端,设置关闭标志,然后关闭窗口。而在取消时直接关闭窗口,不发送事件,确保不会重复触发关闭请求。

  • 整体效果:这修复了死循环问题,现在保存时窗口正常关闭,取消时也直接关闭,不会反复弹出对话框。😄

不小心写死循环窗口弹出了

作者: xingwangzhe

本文链接: https://xingwangzhe.fun/posts/505f6391

本文采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。

留言评论

2000年1月1日星期六
00:00:00