首页 > 解决方案 > react route如何导入本地scss文件只适用于一个js文件?

问题描述

在一个带有 React Router 的 React 应用程序中,对于每个路由组件,我希望有一个本地 scss 文件仅适用于该文件。

对于下面的示例,about.js 导入了 about.scss,我想要的是:about.scss 仅在 about.js 中覆盖 app.scss 中的全局样式。但是,它覆盖了应用程序中的所有内容

app.js - 导入的 app.scss 我更喜欢作为全局样式

import React from "react";
import { BrowserRouter as Router, Route, Link } from "react-router-dom";
import "./app.scss";  // global scss
import About from "./about";

export default function App() {
  return (
    <>
      <h1>question about scss in react route</h1>
      <Router>
        <div>
          <ul>
            <li>
              <Link to="/">Home</Link>
            </li>
            <li>
              <Link to="/about">About</Link>
            </li>
          </ul>
          <hr />
          <Route exact path="/" component={Home} />
          <Route path="/about" component={About} />
        </div>
      </Router>
    </>
  );
}
function Home() {
  return (
    <div>
      <h3 className={"myMargin"}>home</h3>
    </div>
  );
}

app.scss(全局样式)

h3.myMargin {
  margin: 10px
}

about.js

import React from "react";
import "./about.scss";

export default function About() {
  return (
    <div>
      <h3 className={"myMargin"}>About</h3>
    </div>
  );
}

about.scss (我想成为本地风格,但是,它适用于应用程序中的任何地方)

h3.myMargin {
  margin: 100px
}

任何建议如何构建我的样式代码?

标签: reactjssassreact-router

解决方案


CSS 的美妙之处(和警告)在于其首字母缩写词的第一个 C ——代表 级联——这意味着有一系列(相当可预测的)规则要遵循。

在这种情况下about.scss,稍后导入,无论如何都会从应用程序覆盖您的 h3。

1)使用容器:

import React from "react";
import "./about.scss";

export default function About() {
  return (
    <div className='about-page'>
      <h3 className="myMargin">About</h3> // note: no need for {"myMargin"}
    </div>
  );
}

// about.scss
.about-page {
  h3.myMargin {
    margin: 10px
  }
}

2) 使用 CSS 模块:

另一种是使用CSS Modules,如果您使用的是相当新的版本,则默认启用create-react-app

import React from "react";
import styles from "./About.module.scss";

export default function About() {
  return (
    <div>
      <h3 className={styles.myMargin}>About</h3>
    </div>
  );
}

// About.module.scss
.myMargin {
  margin: 10px
}

这将生成一个唯一的类名,因此您处理的代码将如下所示:

<div>
  <h3 class='About_myMargin_mVxOd>About</h3>
</div>

随机哈希(以 mVxOd为例)将允许您的样式不会相互覆盖。

这两种方法各有利弊,使用常规 CSS/SCSS 导入时最大的问题是您受制于 CSS 规则:如果您不小心创建了一个全局类.error,那么规则将级联到任何组件并且很难跟踪。例如,导入 Bootstrap 将覆盖大量您不知道的 CSS 名称(直到您意识到您的 CSS 已关闭)。

另一个问题是,如果上述路由不导入 CSS 文件,但稍后遵循不同的路由路径确实导入了文件,您最终可能会得到不同的样式。这在我们身上发生过几次,因此必须格外小心,尤其是在较大的团队中。

CSS Modules 有一些很大的缺点,第一个是你不能直接通过覆盖另一个 CSS 文件的样式来覆盖它的 CSS 类(因为所说的哈希)。其次,您不能访问 SASS 允许的嵌套 CSS 选择器。

我个人在生产和个人项目中都使用过,两者都同样出色——小心使用时。

还有第三种流行的选项,称为样式化组件。这不是我个人的首选,我也没有太多使用它,但你可以在它的官方页面上了解更多关于它的信息。它看起来像这样:

const Title = styled.h3`
  margin: 10px;
`

render() {
  return <Title>About</Title> // creates an h3 tag
}

最后一个,是 JS 中的 CSS,我也没有使用足够的。


推荐阅读