【问题标题】:Changing the CSS for a React component has effect on all other pages更改 React 组件的 CSS 会影响所有其他页面
【发布时间】:2020-11-15 11:35:15
【问题描述】:

我有一个包含以下文件的 React 组件:

  • src/components/HomePage/index.js
  • src/components/HomePage/style.scss

组件很简单:

import React from 'react';
import './style.scss';

const HomePage = () => {
    return (
        <div className="homepage">
            <h1>Landing page</h1>
        </div>
    );
};

export default HomePage;

style.scss 内,我将样式应用于所有&lt;h1&gt; 标签:

h1 {
    color: #f3f3f3;
    font-family: "Cambria";
    font-weight: normal;
    font-size: 2rem;
}

它按预期工作。但是,我现在看到styles.scss 中的 h1 样式正在应用于我网站上的每个 h1,甚至在不使用此组件的页面上也是如此。

我正在使用 Gatsby,但它本质上是一个 React 应用程序。我的理解是 React 的代码拆分功能会解决这个问题,来自 style.scss 的代码只会包含在使用我的组件的任何页面的捆绑包中。

这就是我要问的原因。我有两个简单的解决方法:

  • style.scss 中的所有内容包装在 .homepage 包装器中
  • 使用 CSS 模块并将文件重命名为 style.module.scss。当我看到人们这样做时,他们总是从 './style.module.scss' 导入样式 - 有没有办法拥有 CSS 模块而不将其分配给这样的对象?

更新:在 React 花了很多时间之后回到这个问题,我认为 React 样式市场存在差距。我认为 CSS 模块在语法上很差,必须手动将所有内容包装在 .home 标记中以对其进行本地化,这是我不想做的手动工作。真的应该有人创建一个自动执行此操作的 React 插件,这样每当我有一个名为 Home.js 的文件并导入 Home.css 时,所有 CSS 都会自动限制为 Home.js,而无需我做任何特别的事情。

【问题讨论】:

标签: javascript css reactjs css-modules


【解决方案1】:

您可以选择下面提到的最简单的方法。

import React from 'react';
import './style.scss';

const HomePage = () => {
    return (
    <div className = "home">
            <div className="homepage">
                <h1>Landing page</h1>
            </div>
    </div>
    );
};

export default HomePage;

您可以将整个 html 包装在一个特定组件名称的 div 中

CSS:

.home h1 {
    color: #f3f3f3;
    font-family: "Cambria";
    font-weight: normal;
    font-size: 2rem;
}

这是最简单的方法。然而,这是我个人的解决方案,因为我在 react 初学者时也面临同样的问题。

【讨论】:

    【解决方案2】:

    如果您想本地化 CSS 规则,那么您必须切换到 modular stylesheets(对于 sass 样式表也是如此)。

    在您当前的结构中,组件会导入非模块化样式表,并且不会使用唯一标识符对更改进行本地化。因此,添加的规则存在于全局范围内,没有唯一的标识符来本地化它们,以便只有选定的组件才能理解它们。这意味着它们能够轻松覆盖之前建立的同名规则(导入顺序在这里很重要,因为它将决定捆绑器如何附加输出样式表)。

    因此,不要在 ./style.scss 文件中保存与组件相关的规则,而是将其重命名为 ./index.module.scss,然后您将在组件中使用它,如下所示:

    import React from 'react';
    import styles from './index.module.scss';
    
    const HomePage = () => {
        return (
            <div className={style.homepage}>
                <h1 className={style.heading}>Landing page</h1>
            </div>
        );
    };
    
    export default HomePage;
    

    你的样式表看起来像:

    .heading {
        color: #f3f3f3;
        font-family: "Cambria";
        font-weight: normal;
        font-size: 2rem;
    }
    

    免责声明

    我已将样式约定从按标签选择元素更改为按类选择它们,因为按标签定位元素被广泛认为是一种不好的做法[ref],但如果你想维护它,那么你会为此类规则提供父范围(它已经存在,因为父 &lt;div/&gt; 元素具有分配的类。 在这种情况下,实现如下所示:

    import React from 'react';
    import styles from './index.module.scss';
    
    const HomePage = () => {
        return (
            <div className={style.homepage}>
                <h1>Landing page</h1>
            </div>
        );
    };
    
    export default HomePage;
    

    和样式:

    .homepage {
        h1 {
            color: #f3f3f3;
            font-family: "Cambria";
            font-weight: normal;
            font-size: 2rem;
        }
    }
    

    【讨论】:

    • 谢谢,您的第二个解决方案就是我所做的。我实际上也在修改这个 CSS 文件中的 body 标签,所以我不想沿着 CSS 模块路线走。我想这只是改变了我对代码拆分的理解。所以我认为所有 React 组件的所有 CSS 都被编译成一个大的 CSS 包,在第一次加载时加载是否正确?如果这是真的,那么我真的不知道代码拆分是如何工作的。
    • 这非常正确(但是可能存在偏差,因此请不要引用我并将其视为经验法则)。模块只是在规则前面加上唯一标识符。但正如答案中所述,我认为您的问题的根源是通过标签类型选择器提供样式 - 最好避免它。
    • 只是读到这里,看起来 React 默认不实现代码拆分——甚至像 Next.js 和 Gatsby 这样的风格——如果你想实现我认为的默认行为,你必须实现通过 React.lazy() 延迟加载。很高兴知道!我将更新我的问题以包含此信息。感谢您的帮助:)
    最近更新 更多