如何在Electron中混合使用自定义撤销逻辑与webContents.undo()方法
实现方案
要判断当前focusedWin.webContents是否可以处理撤销操作,核心是查询当前页面上下文的撤销命令可用状态,Electron主进程可以通过向渲染进程注入JS执行的方式拿到该状态,完整实现如下:
完整菜单项代码
{ label: 'Undo', accelerator: 'CmdOrCtrl+Z', click: async function(menuItem, focusedWin) { // 向当前聚焦窗口注入JS查询撤销命令是否可用 const canUndo = await focusedWin.webContents.executeJavaScript(` document.queryCommandEnabled('undo') `) if (canUndo) { focusedWin.webContents.undo() } else { // 此处运行你的自定义撤销逻辑 } } }
方案说明
document.queryCommandEnabled 虽然被标准标记为废弃,但目前Electron内嵌的所有Chromium版本都完全支持该API,判断精度最高,可以直接识别可编辑元素中是否存在可撤销的历史栈。
兼容替代方案
如果你担心未来API被移除,可以改用判断当前焦点是否位于可编辑元素的方案,兼容性更强:
{ label: 'Undo', accelerator: 'CmdOrCtrl+Z', click: async function(menuItem, focusedWin) { const isFocusedEditable = await focusedWin.webContents.executeJavaScript(` const activeEl = document.activeElement; if (!activeEl) false; activeEl.tagName === 'TEXTAREA' || (activeEl.tagName === 'INPUT' && ['text','password','search','number','email','url'].includes(activeEl.type)) || activeEl.isContentEditable `) if (isFocusedEditable) { focusedWin.webContents.undo() } else { // 此处运行你的自定义撤销逻辑 } } }
该方案的缺点是无法判断可编辑元素内是否真的有可撤销的历史,但即使没有可撤销内容,调用webContents.undo()也不会产生任何报错或副作用,完全可以满足绝大多数场景的需求。
Redo逻辑适配
重做的实现逻辑完全一致,只需要将代码中所有undo替换为redo即可。
内容的提问来源于stack exchange,提问作者YannZeRookie
相关产品推荐
相关产品推荐

