改变 <body> 元素的样式

IT技术 reactjs material-ui
2021-05-14 08:30:10

我是 React 的新手,所以这可能很简单,但我一生都无法在文档中找到任何内容,因为该元素在 ReactDOM 之外。

我使用 material-ui 作为用户界面,它提供了两个主题:(lightBaseTheme默认)和darkBaseTheme深色。各种白天和黑夜模式。问题是既没有对 应用任何样式,<body>因此页面背景不遵循主题。深色主题使用白色文本,默认白色背景上不显示。

我怀疑我需要找到一个编程解决方案并根据当前加载的主题设置背景颜色。

但是如何?我曾尝试将代码放在顶级组件的 componentDidUpdate 方法中,但这似乎总是返回浅色主题。在任何情况下,我都不确定直接写入 DOM 是否是一个好习惯,即使该body元素在任何会受 React 影响的范围之外。

export default class app extends React.Component {

    componentDidUpdate () {
        const muiTheme = getMuiTheme();
        const canvasColor = muiTheme.palette.canvasColor;
        document.body.style.backgroundColor = canvasColor;
    }

    render () {
        const muiTheme = getMuiTheme();
        return (
            <MuiThemeProvider muiTheme={getMuiTheme(darkBaseTheme)}>
                <span>Rest of the app goes here</span>
            </MuiThemeProvider>
        );
    }
};

即使在渲染调用中设置了 lightBaseTheme,在 componentDidUpdate 中对 getMuiTheme 的调用也始终返回 lightBaseTheme。

我或许应该补充一点,最终目的是能够即时更改主题,因此<body无法直接为元素设置样式

3个回答

如果可能,最好的解决方案是div在 React 应用程序中使用顶层以及样式props来解决您的问题。

但是,您现在拥有的将无法工作,因为componentDidUpdate()在初始化时不会被调用,并且您似乎没有在加载后使用 props/state 更新它。

componentDidUpdate()在更新发生后立即调用。初始渲染不会调用此方法。react文档

相反,使用componentDidMount(),它会在组件安装到您的 DOM 后立即调用。

componentDidMount()在组件安装后立即调用。需要 DOM 节点的初始化应该在这里进行。如果您需要从远程端点加载数据,这是实例化网络请求的好地方。在此方法中设置状态将触发重新渲染。react文档

这是一篇关于组件生命周期的好文章

您可以使用 document.body.className。查看w3schools而 componentDidMount 是放置它的更好的地方。

您可以在“ref”回调期间捕获主题并将其分配给变量。然后在 componentDidMount() 中选取该变量(仅调用一次,而 componentDidUpdate() 会在props和状态更改时随时调用):

export default class app extends React.Component {

    componentDidMount() {
        const canvasColor = this.theme.palette.canvasColor;
        document.body.style.backgroundColor = canvasColor;
    }

    render () {
        const muiTheme = getMuiTheme();
        return (
            <MuiThemeProvider ref={ref => (this.theme = ref.props.muiTheme)} muiTheme={getMuiTheme(darkBaseTheme)}>
                <span>Rest of the app goes here</span>
            </MuiThemeProvider>
        );
    }
};