在React Material-UI中实现全局主题

时间:2019-08-19 09:01:57

标签: typescript material-ui react-dom

我对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>
    }
}

以下是结果。

这是菜单完全最小化的时候。 Result

这是一切扩展的时候。 Menu opened

现在,我的问题是:

  1. 为什么右边的面板呈灰色?如何将菜单面板更改为蓝色?
  2. 只要窗口有足够的宽度,我就需要打开抽屉。我可以做隐藏的部分,但是为什么它出现在我的内容部分的顶部呢?如何使其在左侧持久?
  3. 为什么菜单水平展开?如何使其垂直扩展?
  4. 我不想为每个组件做一个布局,因此我不想要一个程式化的组件。我将在整个项目中使用一个全局主题。怎么做?我遵循了文档示例,但是仍然像上面的示例一样。顺便说一下,我并不完全理解该文档,因为它倾向于使用函数,而我所有的项目都是基于类的。

代码沙箱:https://codesandbox.io/embed/theme-test-gwutc

谢谢。

2 个答案:

答案 0 :(得分:0)

我将回答1和4,因为现在我不知道2,3的答案。

  1. 该面板为浅灰色,因为它是纸张的默认颜色(抽屉在引擎盖下使用纸张)。
    纸张不受调色板影响。主要
    为了全局更改纸张背景颜色,您可以执行以下操作:

    const theme = createMuiTheme({
      palette: {
        type: "dark",
        primary: blue,
        secondary: lightGreen,
        background: {
          paper: "blue" // drawers (and papers) will be blue because of this line.
        }
      }
    });
    
  2. 您可以非常轻松地将全局主题应用于所有material-ui组件。 您已经通过用ThemeProvider包装应用程序来完成此操作,所有要做的事情就是正确地编辑主题。
    例如:如果要覆盖抽屉的默认背景颜色,也可以这样做(比上面的选项1更好,因为它不适用于纸张组件):

    const theme = createMuiTheme({
      overrides: { // you declare you override default material-ui styles
       MuiDrawer: {
         paper: {
           backgroundColor: 'blue',
         }
       }
      }
    });
    

答案 1 :(得分:0)

我已经解决了所有问题。 @ido回答的数字1和4。

使用@ido的解决方案的2号答案是放置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已更新为固定的。