使用 React JS 右键单击菜单
Right Click Menu using React JS
我想知道是否有最好的 practice/correct 方法来为 React 组件设置右键单击菜单。
我目前有这个...
// nw is nw.gui from Node-Webkit
componentWillMount: function() {
var menu = new nw.Menu();
menu .append(new nw.MenuItem({
label: 'doSomething',
click: function() {
// doSomething
}
}));
// I'd like to know if this bit can be done in a cleaner/more succinct way...
// BEGIN
var that = this;
addEventListener('contextmenu', function(e){
e.preventDefault();
// Use the attributes property to uniquely identify this react component
// (so different elements can have different right click menus)
if (e.target.attributes[0].nodeValue == that.getDOMNode().attributes[0].nodeValue) {
menu.popup(e.x, e.y);
}
})
// END
},
这行得通,但感觉有点乱,我想知道是否可以使用另一种方法,如能提供任何信息,我们将不胜感激,
谢谢!
更新:
想通了 - 这是您可以做的
var addMenu;
componentWillMount: function() {
addMenu = new nw.Menu();
addMenu.append(new nw.MenuItem({
label: 'doSomething',
click: function() {
// doSomething
}
}));
},
contextMenu: function(e) {
e.preventDefault();
addMenu.popup(e.clientX, e.clientY);
},
render: function(){
return <button onClick={this.handleClick} onContextMenu={this.contextMenu}>SomethingUseful</button>
}
在 render 中,您可以将一个函数传递给 onContextMenu,以便在该 React 组件发生右键单击时使用。
弹出菜单需要注意的事项很少:
- 它应该远离其父级和兄弟级呈现 - 最好在 document.body
的最后一个子级的叠加层中
- 特殊逻辑应该注意它始终显示在屏幕上并且不会被屏幕边缘裁剪
- 如果涉及层次结构,子弹出窗口应与上一个弹出窗口(开启者)中的项目对齐。
我创建了一个库,您可以使用它来完成所有这些:
我在使用 Material UI 时也在寻找解决方案,所以你要做的是首先禁用浏览器的默认行为,然后右键单击,然后添加你想要的菜单想要,这是工作代码:
import React from 'react';
import { withStyles } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';
import Menu from '@material-ui/core/Menu';
import MenuItem from '@material-ui/core/MenuItem';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import ListItemText from '@material-ui/core/ListItemText';
import InboxIcon from '@material-ui/icons/MoveToInbox';
import DraftsIcon from '@material-ui/icons/Drafts';
import SendIcon from '@material-ui/icons/Send';
const StyledMenu = withStyles({
paper: {
border: '1px solid #d3d4d5',
},
})((props) => (
<Menu
elevation={0}
getContentAnchorEl={null}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'center',
}}
transformOrigin={{
vertical: 'top',
horizontal: 'center',
}}
{...props}
/>
));
const StyledMenuItem = withStyles((theme) => ({
root: {
'&:focus': {
backgroundColor: theme.palette.primary.main,
'& .MuiListItemIcon-root, & .MuiListItemText-primary': {
color: theme.palette.common.white,
},
},
},
}))(MenuItem);
export default function CustomizedMenus() {
const [anchorEl, setAnchorEl] = React.useState(null);
const handleClick = (event) => {
event.preventDefault();
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
return (
<div>
<Button
aria-controls="customized-menu"
aria-haspopup="true"
variant="contained"
color="primary"
onContextMenu={handleClick}
>
Open Menu
</Button>
<StyledMenu
id="customized-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
>
<StyledMenuItem>
<ListItemIcon>
<SendIcon fontSize="small" />
</ListItemIcon>
<ListItemText primary="Sent mail" />
</StyledMenuItem>
<StyledMenuItem>
<ListItemIcon>
<DraftsIcon fontSize="small" />
</ListItemIcon>
<ListItemText primary="Drafts" />
</StyledMenuItem>
<StyledMenuItem>
<ListItemIcon>
<InboxIcon fontSize="small" />
</ListItemIcon>
<ListItemText primary="Inbox" />
</StyledMenuItem>
</StyledMenu>
</div>
);
}
我想知道是否有最好的 practice/correct 方法来为 React 组件设置右键单击菜单。
我目前有这个...
// nw is nw.gui from Node-Webkit
componentWillMount: function() {
var menu = new nw.Menu();
menu .append(new nw.MenuItem({
label: 'doSomething',
click: function() {
// doSomething
}
}));
// I'd like to know if this bit can be done in a cleaner/more succinct way...
// BEGIN
var that = this;
addEventListener('contextmenu', function(e){
e.preventDefault();
// Use the attributes property to uniquely identify this react component
// (so different elements can have different right click menus)
if (e.target.attributes[0].nodeValue == that.getDOMNode().attributes[0].nodeValue) {
menu.popup(e.x, e.y);
}
})
// END
},
这行得通,但感觉有点乱,我想知道是否可以使用另一种方法,如能提供任何信息,我们将不胜感激,
谢谢!
更新:
想通了 - 这是您可以做的
var addMenu;
componentWillMount: function() {
addMenu = new nw.Menu();
addMenu.append(new nw.MenuItem({
label: 'doSomething',
click: function() {
// doSomething
}
}));
},
contextMenu: function(e) {
e.preventDefault();
addMenu.popup(e.clientX, e.clientY);
},
render: function(){
return <button onClick={this.handleClick} onContextMenu={this.contextMenu}>SomethingUseful</button>
}
在 render 中,您可以将一个函数传递给 onContextMenu,以便在该 React 组件发生右键单击时使用。
弹出菜单需要注意的事项很少:
- 它应该远离其父级和兄弟级呈现 - 最好在 document.body 的最后一个子级的叠加层中
- 特殊逻辑应该注意它始终显示在屏幕上并且不会被屏幕边缘裁剪
- 如果涉及层次结构,子弹出窗口应与上一个弹出窗口(开启者)中的项目对齐。
我创建了一个库,您可以使用它来完成所有这些:
我在使用 Material UI 时也在寻找解决方案,所以你要做的是首先禁用浏览器的默认行为,然后右键单击,然后添加你想要的菜单想要,这是工作代码:
import React from 'react';
import { withStyles } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';
import Menu from '@material-ui/core/Menu';
import MenuItem from '@material-ui/core/MenuItem';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import ListItemText from '@material-ui/core/ListItemText';
import InboxIcon from '@material-ui/icons/MoveToInbox';
import DraftsIcon from '@material-ui/icons/Drafts';
import SendIcon from '@material-ui/icons/Send';
const StyledMenu = withStyles({
paper: {
border: '1px solid #d3d4d5',
},
})((props) => (
<Menu
elevation={0}
getContentAnchorEl={null}
anchorOrigin={{
vertical: 'bottom',
horizontal: 'center',
}}
transformOrigin={{
vertical: 'top',
horizontal: 'center',
}}
{...props}
/>
));
const StyledMenuItem = withStyles((theme) => ({
root: {
'&:focus': {
backgroundColor: theme.palette.primary.main,
'& .MuiListItemIcon-root, & .MuiListItemText-primary': {
color: theme.palette.common.white,
},
},
},
}))(MenuItem);
export default function CustomizedMenus() {
const [anchorEl, setAnchorEl] = React.useState(null);
const handleClick = (event) => {
event.preventDefault();
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
return (
<div>
<Button
aria-controls="customized-menu"
aria-haspopup="true"
variant="contained"
color="primary"
onContextMenu={handleClick}
>
Open Menu
</Button>
<StyledMenu
id="customized-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
>
<StyledMenuItem>
<ListItemIcon>
<SendIcon fontSize="small" />
</ListItemIcon>
<ListItemText primary="Sent mail" />
</StyledMenuItem>
<StyledMenuItem>
<ListItemIcon>
<DraftsIcon fontSize="small" />
</ListItemIcon>
<ListItemText primary="Drafts" />
</StyledMenuItem>
<StyledMenuItem>
<ListItemIcon>
<InboxIcon fontSize="small" />
</ListItemIcon>
<ListItemText primary="Inbox" />
</StyledMenuItem>
</StyledMenu>
</div>
);
}