首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >基于材料UI和React的定制组件

基于材料UI和React的定制组件
EN

Stack Overflow用户
提问于 2020-06-05 08:58:15
回答 1查看 3.4K关注 0票数 2

我一直在使用物质UI组件来创建我自己的自定义可重用组件包。下面是一个位于包中的自定义组件的示例,只是为了演示目的:

代码语言:javascript
运行
复制
import PropTypes from 'prop-types';
import {makeStyles, ThemeProvider} from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';

const useStyles = makeStyles({
    'buttonPackage': {
        backgroundColor: theme.palette.primary.main,
        color: 'rgba(12, 0, 0, 1)',
        minWidth: '147px',
        padding: '8px 8px 9px 8px',
    },
});

const CustomButton = ({children, theme}) => {
    const classes = useStyles();

    return (
        <ThemeProvider theme={theme}>
            <Button className={classes.buttonPackage}>
                {children}
            </Button>
        </ThemeProvider>
    );
};

export default CustomButton;

如果未将其包装在ThemeProvider中,则全局主题变量不会应用于自定义组件,尽管整个应用程序都封装在ThemeProvider中。

当我试图对具有非常特定的样式且不能被视为可重用的组件的React app部件进行进一步的定制时,就会出现这个问题。下面是React组件的示例,它包含来自包的自定义组件和自定义的内部视图组件,同样,这只是一个演示代码:

代码语言:javascript
运行
复制
import React from 'react';
import {makeStyles} from '@material-ui/core/styles';
import {Button} from '@material-ui/core';
import {CustomButton, theme} from '@name-of-my-package/ui-components';

const useStyles = makeStyles(theme => ({
    buttonApp: {
        height: '100%',
    },
}));

const GenericView = () => {
    const classes = useStyles();

    return (
        <React.Fragment>
            <CustomButton theme={theme}>Button imported from package</CustomButton>
            <Button className={classes.buttonApp}/>Button customized in app</Button>
        </React.Fragment>
    );
};

export default GenericView;

在开发中使用时,一切都很好。在生产中使用时,一些样式属性在包中自定义的组件之间共享,并在react应用程序中进行响应。有效的类是捆绑的,但不应用于页面的第一次加载。当您在应用程序周围单击时(例如,从导航组件更改路由),将应用有效的样式,一切看起来都正常。我注意到,在可重用组件包中定制的组件与在React应用程序中定制的组件之间存在样式重叠。

这种方法是否可能,有自定义组件包,并在应用程序部件(包括主题)中进行进一步的定制?

更新16.06.2020.:目前,解决方案是在项目的app部分完全不使用JSS样式。在应用程序中生成的JSS样式类与在可重用组件包中生成的JSS样式类的名称重叠,这将导致问题的出现。

EN

回答 1

Stack Overflow用户

发布于 2020-12-21 17:26:33

解决这个问题的方法包括几个步骤:

  1. 更改了React部分应用程序Webpack的配置,以包括资料UI别名。这样,React应用程序中使用的Material组件和可重用组件包中的组件都使用了React上下文的相同实例,Material用于主题目的。下面是需要添加的webpack别名属性的一个示例:

代码语言:javascript
运行
复制
alias: {
    'react': require.resolve('react'),
    'react-dom': require.resolve('react-dom'),
    '@material-ui/core': path.resolve('./node_modules/@material-ui/core'),
    '@material-ui/core/styles': path.resolve('./node_modules/@material-ui/core/styles'),
    '@material-ui/lab': path.resolve('./node_modules/@material-ui/lab'),
    '@material-ui/icons': path.resolve('./node_modules/@material-ui/icons'),
    '@material-ui/pickers': path.resolve('./node_modules/@material-ui/pickers'),
},

  1. 在使用组件时更改了导入组件的方式。如果导入组件,请使用webpack别名中定义的路径。例如,不要导入按钮组件,比如:

代码语言:javascript
运行
复制
import Button from '@material-ui/core/Button';

以如下方式导入:

代码语言:javascript
运行
复制
import {Button} from '@material-ui/core';

  1. 在可重用组件包卷配置中,材料UI包被设置为外部依赖项。这样,可重用组件应该使用安装在应用程序的React部分中的material:

代码语言:javascript
运行
复制
external: [
    'react',
    'react-dom',
    '@material-ui/core',
    '@material-ui/core/styles',
    '@material-ui/lab',
    '@material-ui/icons',
    '@material-ui/pickers',
],

  1. 还添加了一件事,在可重用组件包中创建了一个新组件,MyStylesProvider。此包装器向为可重用组件生成的样式类添加了唯一的前缀。这样,在生产中,就不会出现样式的重叠:

代码语言:javascript
运行
复制
import React from 'react';
import {
    StylesProvider,
    createGenerateClassName,
} from '@material-ui/core/styles';

const generateClassName = createGenerateClassName({
    productionPrefix: 'so', // change this string to whatever you like
    seed: 'StackOverflow', // change this string to whatever you like
});

const MyStylesProvider = props => {
    return (
        <StylesProvider
            injectFirst={true}
            generateClassName={generateClassName}
        >
            {props.children}
        </StylesProvider>
    );
};

export default MyStylesProvider;

然后,我使用它在应用程序的反应部分如下:

代码语言:javascript
运行
复制
import React from 'react';
import {theme, MyStylesProvider} from '@package/reusable-components';
import {renderRoutes} from 'react-router-config';
import {ThemeProvider} from '@material-ui/core/styles';
import {CssBaseline} from '@material-ui/core';

const AppView = ({route}) => (
    <ThemeProvider theme={theme}>
        <CssBaseline />
        <MyStylesProvider>
            {renderRoutes(route.routes)}
        </MyStylesProvider>
    </ThemeProvider>
);

export default AppView;

这可能不是最理想的方法,但它是有效的。我想听听其他人在导出可重用材料UI组件方面的意见和经验。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62211659

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档