Javascript 单击其他位置时关闭材质UI组件
我已经使用MaterialUI默认组件构建了一个组件。这是菜单。我想在用户单击菜单外的任何位置后关闭此菜单 我怎么做?图标菜单可以做到这一点。单击主体上的任何其他位置时,菜单将关闭,但菜单组件不会关闭。在查看图标菜单代码后,我注意到它是如何通过一些更改呈现菜单组件的,但找不到触发关闭的函数 下面是图标菜单的代码Javascript 单击其他位置时关闭材质UI组件,javascript,reactjs,Javascript,Reactjs,我已经使用MaterialUI默认组件构建了一个组件。这是菜单。我想在用户单击菜单外的任何位置后关闭此菜单 我怎么做?图标菜单可以做到这一点。单击主体上的任何其他位置时,菜单将关闭,但菜单组件不会关闭。在查看图标菜单代码后,我注意到它是如何通过一些更改呈现菜单组件的,但找不到触发关闭的函数 下面是图标菜单的代码 const React = require('react'); const ReactDOM = require('react-dom'); const ReactTransitionG
const React = require('react');
const ReactDOM = require('react-dom');
const ReactTransitionGroup = require('react-addons-transition-group');
const ClickAwayable = require('../mixins/click-awayable');
const StylePropable = require('../mixins/style-propable');
const Events = require('../utils/events');
const PropTypes = require('../utils/prop-types');
const Menu = require('../menus/menu');
const DefaultRawTheme = require('../styles/raw-themes/light-raw-theme');
const ThemeManager = require('../styles/theme-manager');
const IconMenu = React.createClass({
mixins: [StylePropable, ClickAwayable],
contextTypes: {
muiTheme: React.PropTypes.object,
},
propTypes: {
closeOnItemTouchTap: React.PropTypes.bool,
iconButtonElement: React.PropTypes.element.isRequired,
iconStyle: React.PropTypes.object,
openDirection: PropTypes.corners,
onItemTouchTap: React.PropTypes.func,
onKeyboardFocus: React.PropTypes.func,
onMouseDown: React.PropTypes.func,
onMouseLeave: React.PropTypes.func,
onMouseEnter: React.PropTypes.func,
onMouseUp: React.PropTypes.func,
onTouchTap: React.PropTypes.func,
menuStyle: React.PropTypes.object,
style: React.PropTypes.object,
touchTapCloseDelay: React.PropTypes.number,
},
getDefaultProps() {
return {
closeOnItemTouchTap: true,
openDirection: 'bottom-left',
onItemTouchTap: () => {},
onKeyboardFocus: () => {},
onMouseDown: () => {},
onMouseLeave: () => {},
onMouseEnter: () => {},
onMouseUp: () => {},
onTouchTap: () => {},
touchTapCloseDelay: 200,
};
},
//for passing default theme context to children
childContextTypes: {
muiTheme: React.PropTypes.object,
},
getChildContext () {
return {
muiTheme: this.state.muiTheme,
};
},
getInitialState () {
return {
muiTheme: this.context.muiTheme ? this.context.muiTheme : ThemeManager.getMuiTheme(DefaultRawTheme),
iconButtonRef: this.props.iconButtonElement.props.ref || 'iconButton',
menuInitiallyKeyboardFocused: false,
open: false,
};
},
//to update theme inside state whenever a new theme is passed down
//from the parent / owner using context
componentWillReceiveProps (nextProps, nextContext) {
let newMuiTheme = nextContext.muiTheme ? nextContext.muiTheme : this.state.muiTheme;
this.setState({muiTheme: newMuiTheme});
},
componentWillUnmount() {
if (this._timeout) clearTimeout(this._timeout);
},
componentClickAway() {
this.close();
},
render() {
let {
className,
closeOnItemTouchTap,
iconButtonElement,
iconStyle,
openDirection,
onItemTouchTap,
onKeyboardFocus,
onMouseDown,
onMouseLeave,
onMouseEnter,
onMouseUp,
onTouchTap,
menuStyle,
style,
...other,
} = this.props;
let open = this.state.open;
let openDown = openDirection.split('-')[0] === 'bottom';
let openLeft = openDirection.split('-')[1] === 'left';
let styles = {
root: {
display: 'inline-block',
position: 'relative',
},
menu: {
top: openDown ? 12 : null,
bottom: !openDown ? 12 : null,
left: !openLeft ? 12 : null,
right: openLeft ? 12 : null,
},
};
let mergedRootStyles = this.prepareStyles(styles.root, style);
let mergedMenuStyles = this.mergeStyles(styles.menu, menuStyle);
let iconButton = React.cloneElement(iconButtonElement, {
onKeyboardFocus: this.props.onKeyboardFocus,
iconStyle: this.mergeStyles(iconStyle, iconButtonElement.props.iconStyle),
onTouchTap: (e) => {
this.open(Events.isKeyboard(e));
if (iconButtonElement.props.onTouchTap) iconButtonElement.props.onTouchTap(e);
},
ref: this.state.iconButtonRef,
});
let menu = open ? (
<Menu
{...other}
animated={true}
initiallyKeyboardFocused={this.state.menuInitiallyKeyboardFocused}
onEscKeyDown={this._handleMenuEscKeyDown}
onItemTouchTap={this._handleItemTouchTap}
openDirection={openDirection}
style={mergedMenuStyles}>
{this.props.children}
</Menu>
) : null;
return (
<div
className={className}
onMouseDown={onMouseDown}
onMouseLeave={onMouseLeave}
onMouseEnter={onMouseEnter}
onMouseUp={onMouseUp}
onTouchTap={onTouchTap}
style={mergedRootStyles}>
{iconButton}
<ReactTransitionGroup>{menu}</ReactTransitionGroup>
</div>
);
},
isOpen() {
return this.state.open;
},
close(isKeyboard) {
if (this.state.open) {
this.setState({open: false}, () => {
//Set focus on the icon button when the menu close
if (isKeyboard) {
let iconButton = this.refs[this.state.iconButtonRef];
ReactDOM.findDOMNode(iconButton).focus();
iconButton.setKeyboardFocus();
}
});
}
},
open(menuInitiallyKeyboardFocused) {
if (!this.state.open) {
this.setState({
open: true,
menuInitiallyKeyboardFocused: menuInitiallyKeyboardFocused,
});
}
},
_handleItemTouchTap(e, child) {
if (this.props.closeOnItemTouchTap) {
let isKeyboard = Events.isKeyboard(e);
this._timeout = setTimeout(() => {
this.close(isKeyboard);
}, this.props.touchTapCloseDelay);
}
this.props.onItemTouchTap(e, child);
},
_handleMenuEscKeyDown() {
this.close(true);
},
});
module.exports = IconMenu;
const React=require('React');
const ReactDOM=require('react-dom');
const ReactTransitionGroup=require('react-addons-transition-group');
const ClickAwayable=require(“../mixins/click awayable”);
const StylePropable=require('../mixins/StylePropable');
const Events=require('../utils/Events');
const-PropTypes=require('../utils/prop-types');
const Menu=require(“../Menu/Menu”);
const DefaultRawTheme=require(“../styles/raw-theme/light-raw-theme”);
const-ThemeManager=require(“../styles/theme-manager”);
const IconMenu=React.createClass({
混合:[样式可复制,单击可复制],
上下文类型:{
muiTheme:React.PropTypes.object,
},
道具类型:{
closeOnItemTouchTap:React.PropTypes.bool,
iconButtonElement:React.PropTypes.element.isRequired,
iconStyle:React.PropTypes.object,
openDirection:PropTypes.corners,
onItemTouchTap:React.PropTypes.func,
onKeyboardFocus:React.PropTypes.func,
onMouseDown:React.PropTypes.func,
onMouseLeave:React.PropTypes.func,
onMouseCenter:React.PropTypes.func,
onMouseUp:React.PropTypes.func,
onTouchTap:React.PropTypes.func,
menuStyle:React.PropTypes.object,
样式:React.PropTypes.object,
touchTapCloseDelay:React.PropTypes.number,
},
getDefaultProps(){
返回{
closeOnItemTouchTap:没错,
openDirection:'左下',
onItemTouchTap:()=>{},
onKeyboardFocus:()=>{},
onMouseDown:()=>{},
onMouseLeave:()=>{},
onMouseCenter:()=>{},
onMouseUp:()=>{},
onTouchTap:()=>{},
触摸屏关闭延迟:200,
};
},
//用于将默认主题上下文传递给子级
childContextTypes:{
muiTheme:React.PropTypes.object,
},
getChildContext(){
返回{
博物馆:这个。州。博物馆,
};
},
getInitialState(){
返回{
muiteme:this.context.muiteme?this.context.muiteme:themanager.getmuiteme(DefaultRawTheme),
iconButtonRef:this.props.iconButtonElement.props.ref | | |“iconButton”,
menuInitiallyKeyboardFocused:false,
开:错,
};
},
//每当传递新主题时更新主题内部状态
//从父/所有者使用上下文
组件将接收道具(nextProps、nextContext){
让newMuiTheme=nextContext.muiTheme?nextContext.muiTheme:this.state.muiTheme;
this.setState({muiTheme:newMuiTheme});
},
组件将卸载(){
if(this.\u timeout)cleartimout(this.\u timeout);
},
组件ClickAway(){
这个。关闭();
},
render(){
让{
类名,
closeOnItemTouchTap,
图标按钮元素,
iconStyle,
开放方向,
奥尼姆图赫塔普,
键盘焦点,
一下楼,
离开时,
在MouseCenter,
一起来,,
奥图奇塔普,
梅努斯泰尔,
风格
…其他,
}=这是道具;
让打开=this.state.open;
让openDown=openDirection.split('-')[0]='bottom';
让openLeft=openDirection.split('-')[1]='left';
让样式={
根目录:{
显示:“内联块”,
位置:'相对',
},
菜单:{
顶部:打开向下?12:null,
底部:!openDown?12:空,
左:!openLeft?12:空,
右:openLeft?12:null,
},
};
让mergedRootStyles=this.prepareStyles(style.root,style);
让mergedMenuStyles=this.mergeStyles(styles.menu,menuStyle);
让iconButton=React.cloneElement(iconButtonElement{
onKeyboardFocus:this.props.onKeyboardFocus,
iconStyle:this.mergeStyles(iconStyle,iconButtonElement.props.iconStyle),
onTouchTap:(e)=>{
打开(Events.isKeyboard(e));
if(iconButtonElement.props.onTouchTap)iconButtonElement.props.onTouchTap(e);
},
ref:this.state.iconButtonRef,
});
让菜单=打开(
{this.props.children}
):null;
返回(
{iconButton}
{menu}
);
},
isOpen(){
返回此.state.open;
},
关闭(智能键盘){
if(this.state.open){
this.setState({open:false},()=>{
//当菜单关闭时,在图标按钮上设置焦点
如果(智能键盘){
让iconButton=this.refs[this.state.iconButtonRef];
findDOMNode(iconButton.focus();
setKeyboardFocus();
}
});
}
},
打开(菜单初始锁定){
如果(!this.state.open){
这是我的国家({
开放:是的,
menuInitiallyKeyboardFocused:menuInitiallyKeyboardFocused,
});
}
},
_handleItemTouchTap(e,儿童){
如果(此.props.closeOnItemTouchTap){
让isKeyboard=Events.isKeyboard(e);
这个。_timeout=setTimeout(()=>{
这个。关闭(isKeyboard);
},this.props.touchTapCloseDelay);
}
this.props.onItemTouchTap(e,child);
},
_HandleMenuesKeyDown(){
这个。关闭(true);
},
});
module.exports=IconMenu;
此行为由单击可访问列表给出,您可以找到源代码
只需在自定义组件中导入(或要求)它,然后添加一个componentClickAway
方法,该方法将触发菜单关闭
const ClickAwayable = require('material-ui/lib/mixins/click-awayable')
const CustomMenu = React.createClass({
mixins: [ClickAwayable],
componentClickAway () {
// close your menu
}
})
这意味着他们在某个发行版中不推荐使用它,您必须找出他们在哪个版本中引入了useLayerForClickAway={true}。如果设置了,它就可以工作了