【问题标题】:Couldn't use the same classname across components. CSS is not being scoped inside a style component不能跨组件使用相同的类名。 CSS 不在样式组件内
【发布时间】:2021-02-19 05:58:24
【问题描述】:

我遇到的问题似乎违背了 CSS 在 JS 中的目的。我正在使用样式组件。当我尝试使用在样式组件内的反应树中某处使用的类名时。上面的组件类名样式不知何故被应用到我在树下(非常)使用的类名。

重现步骤

在 React 项目中的任何位置渲染 UpperComponent

const StyledContainer = styled.div`
  .title {
    color: red;
    margin-bottom: 32px;
  }
`;

const UpperComponent = () => {
  return (
    <StyledContainer>
      <FirstComponent />
      <h4 className="title"> text inside upper component </h4>
    </StyledContainer>
  );
};


const FirstStyledContainer = styled.div``;

const FirstComponent = () => {
  return (
    <FirstStyledContainer>
      <h4 className="title">text inside first component</h4>
      <SecondComponent />
    </FirstStyledContainer>
  );
};

const SecondComponent = () => {
  return (
    <div>
      <h4 className="title">text inside second component</h4>
      <ThirdComponent />
    </div>
  );
};

const ThirdComponent = () => {
  return (
    <div>
      <h4 className="title">text inside second component </h4>
    </div>
  );
};

预期行为

UpperComponent 中的title 类名不应影响其具有相同类名的后代元素。它的范围应该仅限于 &lt;h4 className="title"&gt; text inside upper component &lt;/h4&gt;

实际行为

.title { color: red; margin-bottom: 32px; } 类样式应用于 UpperComponent 中的所有组件。 title 不知何故归结为 ThirdCompoent,它嵌套在两个组件中。

这是预期的行为还是我错过了一些基本的东西(最佳实践)?

【问题讨论】:

  • 这是预期的行为...与样式化组件无关,实际上在 CSS-in-JS 中你不应该使用 classNames 而是使用库
  • 但是你认为每一个元素都应该是一个样式化的组件吗?
  • 尝试研究 css-in-js 来解决什么,这正是你想要做的
  • 我已经拆分了 css/scss。关键的“首屏”css/scss 使用样式化的组件,任何“首屏”的东西我都会粘贴到 css/scss 文件中以便之后加载。当涉及到样式化组件时,有时我会制作一个反应组件样式化组件,有时我会制作一个特定于元素的组件(但大部分是反应组件)。我也可能只在样式组件中包含移动 scss/css,并将桌面断点内容放在 scss/css 文件中,以便稍后加载。

标签: html css reactjs styled-components css-in-js


【解决方案1】:

如果你想强制规定范围 - 你可以删除类名和/或让“样式化组件”通过创建 TitleStyle 来命名它们(生成随机哈希类名)并附加到标题 div(类名“title”可以删除)。这应该仅适用于该标题。对吧?

另一种选择

是的,FirstComponent 和 SecondComponent(等)将从顶部捕获 css 规则。这对我来说是预期的结果。不像我们在下面这样做!

<div style = {{color:"red"}}>Test</div>

这只会将 css 内联应用于该 div。

我会像这样稍微更改标题类的名称

const StyledContainer = styled.div`
  .title {
    color: red;
    margin-bottom: 32px;
    &.secondary { color: pink; }
    &.thirdly { color: yellow; }
  }
`;

const UpperComponent = () => {
  return (
    <StyledContainer>
      <FirstComponent />
      <h4 className="title"> text inside upper component </h4>
    </StyledContainer>
  );
};

const SecondComponent = () => {
  return (
    <div>
      <h4 className="title secondary">text inside second component</h4>
      <ThirdComponent />
    </div>
  );
};

const ThirdComponent = () => {
  return (
    <div>
      <h4 className="title thirdly">text inside second component </h4>
    </div>
  );
};

& 是一个 SCSS 运算符,适用于样式化组件。 CSS 以这种方式表现更有益,因为向下传递 css 规则更有效。以这种效率工作!如果您想创建网站范围的 CSS 模式,请尽量避免特定定位,除非您确定需要(这应该不太常见)。

我最常做的是,为 react 组件创建了一个样式化的组件,因此每个 react 组件都有一个来处理该 react 组件中的所有 css/scss。

丹尼尔

【讨论】:

  • 但这不是违背了在 JS 中的 CSS 作用域的目的吗?
  • 查看我修改后的答案?告诉我
  • 是的,这非常有效。但我担心的是来自父样式组件的隐式样式。这可能会失控,因为大多数类名都是通用的。
  • 我确实再次编辑了答案,请确保您已阅读最新的答案。所以要清楚。如果您希望样式组件特定于 div,则需要创建 TitleStyle 并附加到该标题。这使得唯一的随机散列类名称。它不会影响其他标题。但最好是重用 CSS,制作站点范围的 CSS。我确实回答了你的问题吗?
【解决方案2】:

这是正常工作的。您正在选择该样式组件中的所有 .titles。

最后,样式组件只会为您创建的每个样式组件生成一个唯一的类名。所以 CSS 的规则在那里仍然有效。

你可以

  1. 您只能选择直系后代.title
    const StyledContainer = styled.div`
     >.title {
      // rules...
     }
    `
  1. 将类名更改为更具体的名称。

  2. 将 CSS 规则嵌套在父级上。所以不是这个,

    const StyledContainer = styled.div`
     .title {
      // rules...
     }
    `

用另一个元素包裹你的 h4 并执行此操作

    const StyledContainer = styled.div`
      .wrapperClassName {
         .title {
          // rules...
         }
      }
    `

【讨论】:

  • 创建 TitleStyle 并附加到标题 div 更实用。这是我认为不必要的复杂性的额外层
猜你喜欢
  • 2021-12-01
  • 2019-05-12
  • 1970-01-01
  • 2018-10-19
  • 2012-10-08
  • 2018-10-18
  • 2019-04-23
  • 2021-09-15
  • 2017-11-03
相关资源
最近更新 更多