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

53 阅读3分钟

关键代码

// 定义一个响应式的引用,用于笔记的文本内容
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

本文链接: xingwangzhe.fun/posts/505f6…

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