react+electron实现自定义右键菜单复制粘贴,可以在 electron app 和 其他应用比如 word txt 之间自由复制粘贴。
有啥问题欢迎留言一起讨论

首先上图看效果

情况一

react+electron实现自定义右键菜单复制粘贴
react+electron实现自定义右键菜单复制粘贴
react+electron实现自定义右键菜单复制粘贴

情况二

react+electron实现自定义右键菜单复制粘贴
react+electron实现自定义右键菜单复制粘贴
react+electron实现自定义右键菜单复制粘贴

首先设置自定义菜单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import { remote, clipboard } from 'electron'

const { Menu, MenuItem } = remote

getContextMenu () {
//new一个菜单

// 监听contextmenu,实现自定义右键菜单
window.addEventListener('contextmenu', function (e) {
e.preventDefault()
let menu = new Menu()

// ↓ 情况一:任何情况下,都显示 复制 和 粘贴 按钮
//添加菜单功能, label: 菜单名称, accelerator:快捷键,click:点击方法
menu.append(new MenuItem({ label: '复制', accelerator: 'CommandOrControl+C', click: copyString }))
//添加菜单分割线
menu.append(new MenuItem({ type: 'separator' }))
//添加菜单功能
menu.append(new MenuItem({ label: '粘贴', accelerator: 'CommandOrControl+V', click: printString }))
// ↑ 情况一

// ↓ 情况二:可复制时,显示复制,可粘贴时显示粘贴
let flag = false // menu中是否有菜单项,true有,false没有
const tagName = document.activeElement.tagName // 焦点元素的tagName
const str = clipboard.readText() // 剪贴板中的内容
const selectStr = _this.getSelection() // 选中的内容
const text = e.target.innerText || '' // 目标标签的innerText
const value = e.target.value || '' // 目标标签的value

if (selectStr) { // 如果有选中内容
flag = true
// 在 选中的元素或者输入框 上面点右键,这样在选中后点别处就不会出现右键复制菜单
if (text.indexOf(selectStr) !== -1 || value.indexOf(selectStr) !== -1) menu.append(new MenuItem({ label: '复制', click: copyString }))
}
if (str && (tagName === 'INPUT' || tagName === 'TEXTAREA')) { // 若为输入框 且 剪贴板中有内容,则显示粘贴菜单
flag = true
menu.append(new MenuItem({ label: '粘贴', click: printString }))
}

// ↑ 情况二


// menu中有菜单项 且(有选中内容 或 剪贴板中有内容)
if (flag && (_this.getSelection() || str)) {
// 将此menu菜单作为 当前窗口 remote.getCurrentWindow() 中的上下文菜单弹出。
menu.popup(remote.getCurrentWindow())
}
}, false)
// 写入剪贴板方法
function copyString () {
const str = getSelection() // 获取选中内容
clipboard.writeText(str) // 写入剪贴板
}
// 获取剪贴版内容写入当前焦点元素中
function printString () {
if (document.activeElement) {
const str = clipboard.readText() // 获取剪贴板内容
document.activeElement.value = str // 写入焦点元素
clipboard.clear() // 清空剪贴板
}
}
}

// 获取选中内容
getSelection () {
var text = ''
if (window.getSelection) { // 除IE9以下 之外的浏览器
text = window.getSelection().toString()
} else if (document.selection && document.selection.type !== 'Control') { //IE9以下,可不考虑
text = document.selection.createRange().text
}
if (text) {
return text
}
}

受控组件使用鼠标点击粘贴无法触发onchange问题

这种情况,可以在提交数据时,使用ref方式,直接调用更新数据的方法来实现数据更改,
我是这样写的

1
2
3
4
5
6
7
8
9
10
11
12
13
// 提交数据时
if (this.acct.value) {
this.changeData('username', this.acct.value)
}
/* 提交数据 */


// 输入框
<input
ref={ref => { this.ipt = ref }
onChange={evt => changeData('username', evt.target.value)}
/* other props */
/>

实现快捷键功能

快捷方式使用 register 方法在 globalShortcut 模块中注册, 即:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import { globalShortcut } from 'electron'
// 系统默认快捷键在app中同样生效。但是若设置了快捷键,且和系统原有的相同,会覆盖系统的。
globalShortcut.register('CommandOrControl+C', () => {
try {
const str = getSelection()
clipboard.writeText(str)
} catch (e){}
})

// 系统默认快捷键在app中同样生效。但是若设置了快捷键,且是系统原有的,会覆盖系统的。
globalShortcut.register('CommandOrControl+V', () => {
try {
const str = clipboard.readText()
document.activeElement.value = str
clipboard.clear()
} catch (e){}
})

避免覆盖系统范围的键盘快捷键.

注册全局快捷方式时, 请务必注意目标操作系统中的现有默认值, 以免覆盖任何现有行为.有关每个操作系统键盘快捷键的概述, 请查看这些文档: