在 React 中实现全局主题 Material-UI
Implement global theme in React Material-UI
我对 React Material-UI 主题有点困惑。
我已尝试将其设置得尽可能基本,但似乎无法以某种方式使其正常工作。
下面是我的代码:
start.tsx
const theme = createMuiTheme({
palette: {
type: 'dark',
primary: blue,
secondary: lightGreen
}
})
ReactDOM.render(
<ThemeProvider theme={theme}>
<BrowserRouter>
<App />
</BrowserRouter>
</ThemeProvider>
,
document.getElementById("root")
)
UserInterfaces.scan();
app.tsx
export class App extends React.Component<IProps, IState> {
constructor(props) {
super(props);
this.state = {
menu: null
}
}
render() {
if (!this.state.menu) {
this.login();
return <div>Loading ... </div>
} else {
return <div className="hx-top-frame">
<div>
<MenuBar menuList={this.state.menu} />
</div>
<div>
Content here
{/* <Content /> */}
</div>
</div>
}
}
}
menubar.tsx
export class MenuBar extends React.Component<IMenuProps, IMenuStates> {
constructor(props) {
super(props);
this.state = { expanded: "" };
}
private setClose() {
this.setState({ expanded: "" });
}
public render() {
let menulist: IMenuArray[] = this.props.menuList.map<IMenuArray>(item => {
return {
path: item.path,
icon: item.icon,
link: Util.hyphenate(item.path)
}
})
return <nav className="hx-menu">
<Hidden smUp>
<Drawer variant="temporary" anchor='left' open={this.state.expanded != ""} onClose={this.setClose.bind(this)} className="left-drawer">
<SubMenu menu={menulist} />
</Drawer>
</Hidden>
<Hidden xsDown>
<Drawer variant="permanent" anchor='left' open={this.state.expanded != ""} onClose={this.setClose.bind(this)} className="left-drawer">
<SubMenu menu={menulist}></SubMenu>
</Drawer>
</Hidden>
</nav >
}
}
submenu.tsx
class SubMenu extends React.Component<ISubMenuProps, IMenuStates> {
constructor(props) {
super(props);
this.state = { expanded: "" };
}
public render() {
let submenu: IMenuItems = {};
let menuitems: IMenuArray[] = [];
this.props.menu.forEach(menu => {
let items = menu.path.split("/");
let parent = items.length > 1;
let name = items.shift();
let child = items.join("/");
if (!parent) {
menuitems.push({ path: name, icon: menu.icon, link: menu.link });
} else {
if (!submenu[name]) submenu[name] = [];
submenu[name].push({ path: child, icon: menu.icon, link: menu.link });
}
})
return <List>
{Object.keys(submenu).map(name => {
let menu = name.split("/").shift();
return <ListItem button className="hx-submenu" key={"m-" + name}>
<span className="hx-nowrap" onClick={() => { this.setState({ expanded: this.state.expanded == name ? "" : name }) }}>
<ListItemText primary={name} key={"t-" + name} />{this.state.expanded == name ? <ExpandLess /> : <ExpandMore />}
</span>
<Collapse in={this.state.expanded == name} timeout="auto" unmountOnExit className="hx-submenu">
<SubMenu menu={submenu[name]} />
</Collapse>
</ListItem>
})}
{menuitems.map(item => {
return <ListItem button component={RouterLink} to={item.link} key={"i-" + item.path}>
<ListItemText primary={item.path} className="hx-menu" key={"l-" + item.path} />
</ListItem>
})}
</List>
}
}
下面是结果。
这是菜单完全最小化的时候。
这是展开所有内容的时候。
现在,我的问题是:
- 为什么右面板是浅灰色的?如何将菜单面板更改为蓝色?
- 只要 window 有足够的宽度,我就需要打开抽屉。我可以做隐藏部分,但为什么它会出现在我的内容部分之上?如何让它在左边持久化?
- 为什么菜单会横向展开?如何让它垂直展开?
- 我不想为每个组件都做一个布局,因此我不想要一个程式化的组件。我将在整个项目中使用的只是一个全局主题。怎么做?我已经按照文档示例进行操作,但它仍然像上面的示例一样。顺便说一句,我并不完全理解该文档,因为它倾向于使用函数,而我的所有项目都基于 类.
代码沙箱:https://codesandbox.io/embed/theme-test-gwutc
谢谢。
我会回答 1 和 4,至于现在我不知道 2,3 的答案。
面板是浅灰色的,因为它是 Paper 的默认颜色(Drawer 在底层使用 Paper)。
纸张不受 palette.primary
的影响
为了全局更改纸张背景颜色,您可以这样做:
const theme = createMuiTheme({
palette: {
type: "dark",
primary: blue,
secondary: lightGreen,
background: {
paper: "blue" // drawers (and papers) will be blue because of this line.
}
}
});
您可以非常轻松地将全局主题应用于所有 material-ui 组件。
你已经通过使用 ThemeProvider 包装你的应用程序来做到这一点,你所要做的就是正确地编辑你的主题。
例如:如果你想覆盖抽屉的默认背景颜色,你也可以这样做(比上面的选项1更好,因为它不适用于纸张组件):
const theme = createMuiTheme({
overrides: { // you declare you override default material-ui styles
MuiDrawer: {
paper: {
backgroundColor: 'blue',
}
}
}
});
我都解决了。 @ido 回答的第 1 和第 4 条。
2 号答案,使用@ido 的解决方案,是将 display:flex
和纸张宽度设置为固定数字。
下面是第 3 题的答案。
submenu.tsx
.
.
<li>
<ListItem button className="hx-submenu" key={"m-" + name}>
<ListItemText primary={name} key={"t-" + name} onClick={() => {
this.setState({
expanded: this.state.expanded == name ? "" : name
});
}}
/>
{this.state.expanded == name ? <ExpandLess /> : <ExpandMore />}
</ListItem>
<Collapse
in={this.state.expanded == name}
timeout="auto"
unmountOnExit
className="hx-submenu"
>
<SubMenu menu={submenu[name]} />
</Collapse>
</li>
.
.
问题是我把 <Collapse>
放在了 <ListItem>
里面。因此,我看不到 <span>
的必要性,因此将其删除。
codepen 已更新为固定的。
我对 React Material-UI 主题有点困惑。
我已尝试将其设置得尽可能基本,但似乎无法以某种方式使其正常工作。
下面是我的代码:
start.tsx
const theme = createMuiTheme({
palette: {
type: 'dark',
primary: blue,
secondary: lightGreen
}
})
ReactDOM.render(
<ThemeProvider theme={theme}>
<BrowserRouter>
<App />
</BrowserRouter>
</ThemeProvider>
,
document.getElementById("root")
)
UserInterfaces.scan();
app.tsx
export class App extends React.Component<IProps, IState> {
constructor(props) {
super(props);
this.state = {
menu: null
}
}
render() {
if (!this.state.menu) {
this.login();
return <div>Loading ... </div>
} else {
return <div className="hx-top-frame">
<div>
<MenuBar menuList={this.state.menu} />
</div>
<div>
Content here
{/* <Content /> */}
</div>
</div>
}
}
}
menubar.tsx
export class MenuBar extends React.Component<IMenuProps, IMenuStates> {
constructor(props) {
super(props);
this.state = { expanded: "" };
}
private setClose() {
this.setState({ expanded: "" });
}
public render() {
let menulist: IMenuArray[] = this.props.menuList.map<IMenuArray>(item => {
return {
path: item.path,
icon: item.icon,
link: Util.hyphenate(item.path)
}
})
return <nav className="hx-menu">
<Hidden smUp>
<Drawer variant="temporary" anchor='left' open={this.state.expanded != ""} onClose={this.setClose.bind(this)} className="left-drawer">
<SubMenu menu={menulist} />
</Drawer>
</Hidden>
<Hidden xsDown>
<Drawer variant="permanent" anchor='left' open={this.state.expanded != ""} onClose={this.setClose.bind(this)} className="left-drawer">
<SubMenu menu={menulist}></SubMenu>
</Drawer>
</Hidden>
</nav >
}
}
submenu.tsx
class SubMenu extends React.Component<ISubMenuProps, IMenuStates> {
constructor(props) {
super(props);
this.state = { expanded: "" };
}
public render() {
let submenu: IMenuItems = {};
let menuitems: IMenuArray[] = [];
this.props.menu.forEach(menu => {
let items = menu.path.split("/");
let parent = items.length > 1;
let name = items.shift();
let child = items.join("/");
if (!parent) {
menuitems.push({ path: name, icon: menu.icon, link: menu.link });
} else {
if (!submenu[name]) submenu[name] = [];
submenu[name].push({ path: child, icon: menu.icon, link: menu.link });
}
})
return <List>
{Object.keys(submenu).map(name => {
let menu = name.split("/").shift();
return <ListItem button className="hx-submenu" key={"m-" + name}>
<span className="hx-nowrap" onClick={() => { this.setState({ expanded: this.state.expanded == name ? "" : name }) }}>
<ListItemText primary={name} key={"t-" + name} />{this.state.expanded == name ? <ExpandLess /> : <ExpandMore />}
</span>
<Collapse in={this.state.expanded == name} timeout="auto" unmountOnExit className="hx-submenu">
<SubMenu menu={submenu[name]} />
</Collapse>
</ListItem>
})}
{menuitems.map(item => {
return <ListItem button component={RouterLink} to={item.link} key={"i-" + item.path}>
<ListItemText primary={item.path} className="hx-menu" key={"l-" + item.path} />
</ListItem>
})}
</List>
}
}
下面是结果。
这是菜单完全最小化的时候。
这是展开所有内容的时候。
现在,我的问题是:
- 为什么右面板是浅灰色的?如何将菜单面板更改为蓝色?
- 只要 window 有足够的宽度,我就需要打开抽屉。我可以做隐藏部分,但为什么它会出现在我的内容部分之上?如何让它在左边持久化?
- 为什么菜单会横向展开?如何让它垂直展开?
- 我不想为每个组件都做一个布局,因此我不想要一个程式化的组件。我将在整个项目中使用的只是一个全局主题。怎么做?我已经按照文档示例进行操作,但它仍然像上面的示例一样。顺便说一句,我并不完全理解该文档,因为它倾向于使用函数,而我的所有项目都基于 类.
代码沙箱:https://codesandbox.io/embed/theme-test-gwutc
谢谢。
我会回答 1 和 4,至于现在我不知道 2,3 的答案。
面板是浅灰色的,因为它是 Paper 的默认颜色(Drawer 在底层使用 Paper)。
纸张不受 palette.primary
的影响 为了全局更改纸张背景颜色,您可以这样做:const theme = createMuiTheme({ palette: { type: "dark", primary: blue, secondary: lightGreen, background: { paper: "blue" // drawers (and papers) will be blue because of this line. } } });
您可以非常轻松地将全局主题应用于所有 material-ui 组件。 你已经通过使用 ThemeProvider 包装你的应用程序来做到这一点,你所要做的就是正确地编辑你的主题。
例如:如果你想覆盖抽屉的默认背景颜色,你也可以这样做(比上面的选项1更好,因为它不适用于纸张组件):const theme = createMuiTheme({ overrides: { // you declare you override default material-ui styles MuiDrawer: { paper: { backgroundColor: 'blue', } } } });
我都解决了。 @ido 回答的第 1 和第 4 条。
2 号答案,使用@ido 的解决方案,是将 display:flex
和纸张宽度设置为固定数字。
下面是第 3 题的答案。
submenu.tsx
.
.
<li>
<ListItem button className="hx-submenu" key={"m-" + name}>
<ListItemText primary={name} key={"t-" + name} onClick={() => {
this.setState({
expanded: this.state.expanded == name ? "" : name
});
}}
/>
{this.state.expanded == name ? <ExpandLess /> : <ExpandMore />}
</ListItem>
<Collapse
in={this.state.expanded == name}
timeout="auto"
unmountOnExit
className="hx-submenu"
>
<SubMenu menu={submenu[name]} />
</Collapse>
</li>
.
.
问题是我把 <Collapse>
放在了 <ListItem>
里面。因此,我看不到 <span>
的必要性,因此将其删除。
codepen 已更新为固定的。