css-loader css模块嵌套组件规则

时间:2019-07-15 13:45:09

标签: reactjs webpack sass css-loader css-modules

让我们说我以以下方式使用scss模块

A.jsx

import styles from './A.module.scss';
import B from '../B/B.jsx';

const A = props => {
    return <div className={styles.a}>
         <B/>
    </div>;
};

export default A;

B.jsx

import './B.scss';

const B = props => {
    return <div className="b">
    </div>;
};

export default B;

A.module.scss内,我重写B的css规则,如下所示:

.a {
 .b {
    width: 500;
    height: 500;
    background-color: red;
 }
}

然后,我为B中的A实例覆盖的样式没有传递给它,显然是因为它使用的是CSS模块。如何使B的css规则仅适用于A而不适用于全局?

我想也许我必须为要实现此功能的每个组件传递自定义className道具,因此对于此实例,将自定义className道具传递给B并像这样传递它:

<B className={styles.b}/>

,并且在B.jsx中,只需将自定义类应用于该组件。 不是我最喜欢的解决方案,宁愿不添加自定义类,而仅使用自定义选择器.a .b,因为它定义了我要定位的B下的每个A的关系,但是想知道是否有像我正在寻找的更简单的解决方案?

我还不确定className道具是否适用于B嵌套了多个节点,而我正在尝试使用css规则将嵌套节点作为目标的情况。我不能只为每个组件都拥有一个针对每个节点的className道具。

下面是说明这种情况的示例:

B.jsx

import './B.scss';

const B = props => {
    return <div className="b">
        <div className"b-inner1">
            <div className"b-inner2">
                <div className"b-inner3">
                </div>
            </div>
        </div>
    </div>;
};

export default B;

例如,我想在此使用className b-inner3为节点设置样式,该节点可能只是用于帮助B组件的基本布局和我不希望该组件的用户将className传递到该节点。

1 个答案:

答案 0 :(得分:0)

每个组件(与任何其他函数一样)都对实现细节进行了一些抽象,它还具有一个API,该API是您与组件使用者之间的契约。
如果您没有公开classNamestyle道具,那意味着您基本上是在说“此组件将不保证在DOM中始终保持相同的结构或公共类名称”。如果有人会超越您的课程,则表示他/她正在冒险,并且可能会面临重大变化。

如果您确实想让消费者具有覆盖或添加样式的能力,那么您会看到2(或3)个主要选项:

  1. 为您要允许的每个节点接受styleclassName道具 样式:

    const MyComponent = (props) => (
        <div className={`${styles.myStyle1} ${props.publicStyle1}`}>
            <div className={`${styles.myStyle2} ${props.publicStyle2}`}>
                <button
                    className={`${styles.button}
                    ${props.publicStyleButton}`}
                >
                    Click Me
                </button>
            </div>
        </div>
    );
    

    是的,这可能会造成混乱,并且看起来像一个令人困惑的API 消费和维护。

  2. 公开硬编码的类名:

    const MyComponent = (props) => (
        <div className={`${styles.myStyle1} public-style-1`}>
            <div className={`${styles.myStyle2} public-style-2`}>
                <button
                    className={`${styles.button} public-style-button`}
                >
                    Click Me
                </button>
            </div>
        </div>
    );
    

    这样,您的合同说您将始终保留那些公共类名(或重大更改版本)

  3. 通常与样式没有直接关系的另一种方法 称为“复合成分”,您可以将其与以下一种混合使用 上面的方法:

    const MyButton = ({ text, onClick, ...rest }) => (
        <button
            onClick={onClick}
            className={`${styles.button}`}
            {...rest}
        >
            {text}
        </button>
    )
    
    const MyComponent = (props) => (
        <div className={`${styles.myStyle1} public-style-1`}>
            {children}
        </div>
    );
    
    MyComponent.Button = MyButton;
    
    
    /* usage... */
    
    <MyComponent>
        <MyComponent.Button
            text="Click Me"
            className="consumer-class"
            style={{color: 'green'}}
        />
    </MyComponent>
    

    这将使您将组件分解成较小的部分并给予 对您的消费者有更多的控制权。