我正在运行MaterialUI-Next并且我已经尝试了抽屉的所有变体但是当单击抽屉中的项目时我无法关闭它。我知道临时变体允许我这样做,但是当点击任何内容时它会关闭。我只需要在单击ListItem时关闭它。
在我的情况下,我在抽屉中有一个ExpansionPanel,里面有Lists和ListItems。单击ExpansionPanel不应关闭抽屉,抽屉应保持打开状态,因为我还没准备好离开。但是,当我单击抽屉中的ListItem(它们包含component="a"
项)时,抽屉应关闭,组件=“a”导航到其href。
我的代码非常基本且非常简洁,实际上来自MaterialUI-Next Drawers的精确演示。他们还有一个测试代码的游乐场。但无论如何,这是我的一些相关代码
我的抽屉:
<Drawer
variant="persistent" //I tried "temporary", and "permanent" as well
elevation={16}
anchor="right"
open={this.state.open}
// onClick={(open) => this.setState({ open: false })}
// onKeyDown={(open) => this.setState({ open: false })}>
<SystemMenu />
</Drawer>
我的内容存储在SystemMenu中:
import React from 'react';
import { withStyles } from 'material-ui-next/styles';
import List, { ListItem, ListItemText } from 'material-ui-next/List';
import ExpansionPanel, { ExpansionPanelDetails, ExpansionPanelSummary } from 'material-ui-next/ExpansionPanel';
import ListSubheader from 'material-ui-next/List/ListSubheader';
import {ChevronDown} from 'mdi-material-ui';
import Grid from 'material-ui-next/Grid';
const OTHERPAGES = require('data/pages.js');
const systemMenuData = OTHERPAGES['systemMenuPagesItems'];
class SystemMenu extends React.Component {
constructor(props) {
super(props);
this.state = {
expanded: null,
};
}
handleChange = panel => (event, expanded) => {
this.setState({
open: false,
expanded: expanded ? panel : false,
});
};
render() {
const { expanded, open } = this.state;
return (
<div>
<Grid
container>
<Grid item xs={12} style={{padding: 0}}>
<ListSubheader component="div">MENU ITEMS</ListSubheader>
</Grid>
</Grid>
<Grid
container>
<Grid item xs={12}>
<ExpansionPanel
expanded={expanded === 'panel1'}
onChange={this.handleChange('panel1')}>
<ExpansionPanelSummary
expandIcon={<ChevronDown />}>
Players
</ExpansionPanelSummary>
<ExpansionPanelDetails>
<List>
<ListItem
button
component="a"
href="/app/page1">
<ListItemText primary="Page 1" />
</ListItem>
<ListItem
button
component="a"
href="/app/page2">
<ListItemText primary="Page 2" />
</ListItem>
<ListItem
button
component="a"
href="/app/page3">
<ListItemText primary="Page 3" />
</ListItem>
</List>
</ExpansionPanelDetails>
</ExpansionPanel>
</Grid>
</Grid>
</div>
);
}
}
export default withStyles(styles)(SystemMenu);
我在其他帖子中读到,您可以使用道具将onKeyDown={(open) => this.setState({ open: false })}
传递给其子级。但我是React的新手,并且在这个概念上遇到了一些问题。
基本上,我需要让onKeyDown适用于ListItems,而不是实际的抽屉。我可能会或可能不会将我的Drawer变量更改回临时,以便onKeyDown属性可以工作。不太确定。
(请记住上面的链接提供了一个测试代码的操场。比我尝试为React构建一个jFiddle好多了)
修改
我用不同的方式,但不是我的最爱。
通过将SystemMenu中的内容移动到Menu.js文件(我的Drawer导入,函数和状态实时),我能够创建一个带超时的handleClose函数,以便它关闭。这是功能:
handleClose = () => {
if (!this.state.open) {
return;
}
this.timeout = setTimeout(() => {
this.setState({ open: false });
this.setState({ expanded: null });
});
};
这需要持久变量和handleOpen()
函数来保持抽屉打开,直到我单击具有handleClose()
功能的List。所以,我的抽屉现在看起来像这样
<Drawer
variant="persistent"
elevation={16}
anchor="right"
open={this.state.open}
onClick={() => { this.handleOpen(); }}>
...
My System Menu code in here, not too happy about this part. :(
...
</Drawer>
接下来,在包含扩展面板和列表的系统菜单代码中,我将handleClose()
功能添加到列表中,并导航以及关闭抽屉和扩展面板。像这样:
<List
className="quickpanel-navigation"
onClick={() => { this.handleClose(); }}>
.... ListItems code here ....
</List>
这是一个Ok方法,但我更喜欢将SystemMenu代码放在另一个文件中并导入到该文件中并使用props来操作SystemMenu.js文件中Menu.js文件中的结束函数。如果有人想继续帮助我,我会很感激。
答案 0 :(得分:3)
在demo中,他们将所有ListItem包装在处理关闭抽屉的div中:
<div
tabIndex={0}
role="button"
onClick={this.toggleDrawer('left', false)}
onKeyDown={this.toggleDrawer('left', false)}
>
{sideList}
</div>
在此代码中,toggleDrawer
是一个设置用于抽屉open
道具的状态的函数。因此,当按下某个键或在其中一个列表的子项中发生单击时,该事件会冒泡到这些处理程序(只要未使用event.stopPropagation()
)并且状态已更改。
在您的代码中,您不希望扩展程序的点击关闭抽屉,因此您必须以不同方式处理这些事件。
您可以在列表中添加onClick
处理程序:
<ExpansionPanelDetails>
<List onClick={ () => { /* close the drawer here */ } }>
<ListItem
button
component="a"
href="/app/page1">
<ListItemText primary="Page 1" />
</ListItem>
<ListItem
button
component="a"
href="/app/page2">
<ListItemText primary="Page 2" />
</ListItem>
<ListItem
button
component="a"
href="/app/page3">
<ListItemText primary="Page 3" />
</ListItem>
</List>
</ExpansionPanelDetails>
然后,当单击ListItems时,事件将冒泡到List的处理程序,该处理程序设置状态,关闭抽屉。
根据代码的结构,您可能需要修改Drawer的实现以将函数传递给SystemMenu
组件,以便其List上的click处理程序可以设置其父级的状态,因为{{ 1}}影响this.setState
的状态,this
是该组件的当前实例。它不会设置抽屉的状态。
<强>更新强>
根据您的评论,我添加了这一位。
在您的SystemMenu组件中:
- 接受名为closeDrawer
的道具。
- 使用此函数,来自props,作为List
onClick
处理程序
closeDrawer
。this.closeDrawer
作为`closeDrawer <SystemMenu closeDrawer={this.closeDrawer} ...>
这是从子系统SystemMenu中改变父组件Menu的本地状态的一种方法。
答案 1 :(得分:0)
假设你的抽屉在一个类组件中,你可以这样做,从子组件中关闭它。
class MyComponent extends React.Component {
constructor(props){
super(props)
this.state = {
open: false,
}
}
closeDrawer = () => this.setState({ open: false })
render() {
return (
<Drawer
elevation={16}
anchor="right"
open={this.state.open}
onKeyDown={this.closeDrawer}
>
<SystemMenu
closeDrawer={this.closeDrawer}
/>
</Drawer>
)
}
}
然后,您可以从this.props.closeDrawer
内访问SystemMenu
。听起来您想要为列表项添加onClick
处理程序:
<ListItem
button
component="a"
href="/app/page1"
onClick={this.props.closeDrawer}
>
<ListItemText primary="Page 1" />
</ListItem>
答案 2 :(得分:0)
通过PaperProps
将关闭处理程序放置在MuiPaper上:
const handleClose = () => console.log('closing drawer');
const MyDrawer = () => <Drawer PaperProps={{onClick: handleClose}} />
在抽屉内的任何位置单击鼠标,将关闭抽屉。