CSS样式组件:为什么你应该(或不应该)使用它

选择完全适合您需求的样式模块就像选择 JavaScript 框架一样困难。您的最终选择可能取决于项目的规模、公司现有的堆栈或仅仅是品味问题。如果 React 是您的框架,那么样式组件就不能从您的可能性列表中排除。Bas Bastiaans - PanCompany 的前端开发人员 - 最近从“更少”组件迁移到样式化组件,并分享了他之后经历的好处。接下来,他还讨论了在采取他所做的迁移步骤之前必须考虑的一些谈话要点。

什么是样式组件?

Styled-Components 是 React 的一个库,允许您直接在 javascript 中编写 CSS。这称为“css-in-js”。这种方法并不是 React 独有的,您可以使用几乎所有可用的 javascript 框架来实现 css-in-js,但 styled-components 可能是最流行的。如果您熟悉 CSS 的任何方法,那么使用样式组件的步骤就相当简单。当然,从 less 切换到样式组件需要你克服比从经典 CSS 到 CSS 模块更大的学习曲线,但如果你是一名 javascript 开发人员,你会自然地适应它。编写样式的语法仍然是纯粹的 CSS,主要区别在于您可以直接在 JavaScript 中编写它。

让我们看看实现经典 CSS 和样式组件之间的区别。在 CSS 中,您创建全局样式类,将其注入到 javascript 中,并为每个组件确定它是否需要特定的类名。特别是在具有大量组件的大型项目中,这些类可能会相互覆盖,从而导致应用程序中的样式不一致。Styled-components 解决了这个问题,因为您需要在本地确定样式。样式的范围在您的组件内部。

这是可能的,因为样式组件受益于称为标记模板文字(一种使用反引号调用函数的方法)的 JavaScript 功能。通过实际展示可以最好地解释这一点。您可以通过使用“styled”对象定义 React 元素来创建样式组件。这里您可以看到一个带有红色文本且字体大小为 16px 的 div 的简单示例:

import styled from 'styled-components';
const StyledTextBlock = styled.div`
    color: red;
    font-size: 16px;
`;

您可以像这样使用该样式组件:

const App = () =>
    <StyledTextBlock>
       I am a pretty text block
    </StyledTextBlock>

与常规 CSS 相比,本地作用域是一个主要优势,但这并不是切换到样式组件的主要原因。例如,CSS 模块还解决了范围界定问题。最大的优点之一是样式组件允许作为 JavaScript 开发人员创建样式。由于您使用的是模板文字,因此您可以使用 props 动态调整组件。这使您可以非常轻松地更改因数据更改而导致的组件的外观。与常规 CSS 相比,这是一个主要优点,在常规 CSS 中,您必须为每个不同的样式注入不同的类名。

如果你想基于 prop 来设计你的 React 组件的样式,你可以这样做:

const App = () =>
    <StyledTextBlock isBold>
     I am a pretty text block
    </StyledTextBlock>

然后你可以根据该道具调整你的样式,如下所示:

const StyledTextBlock = styled.div`
    color: red;
    font-size: 16px;
    font-weight: ${props => (props.isBold ? 'bold' : 'normal')}
`;

或者,经过一些重构,以更稳健的方式:

const StyledTextBlock = styled.div(({ isBold }) => `
    color: red;
    font-size: 16px;
    font-weight: ${isBold ? 'bold' : 'normal'};
`);

与常规 CSS 相比,样式组件的更多优点

前面的示例已经证明了如何从样式化组件的动态特性中受益。然而,还有很多:

Styled-components 不需要在 CI/CD 管道中执行额外的步骤
另一个优点是构建应用程序要容易得多,因为您不必考虑任何 .css 文件。样式位于您的 javascript 中,因此您只需在管道中构建 javascript 即可。唯一的配置是您可能需要添加样式组件的 babel 插件。

Styled-components 生成唯一的类名
如果您检查之前构建的组件,我们会在 DOM 中看到以下内容:

<div class="sc-hLQSwg eZXEhV”>I am a pretty text block</div>

在“class”后面,您会看到一个生成的唯一名称。这可以确保您几乎不会出现与类名相关的错误。

提示:
如果您使用快照测试,动态生成类可能会很烦人。为了防止这种情况,您可以使用以下库:jest-styled-components

样式化组件使主题变得简单且易于访问
另一个很大的优点是内置的“Themeprovider”。通过该提供程序,您可以创建一个充满预定义颜色、间距和其他值的主题,并将其用于整个 React 应用程序。由于样式组件的动态特性,使用样式组件比使用经典 CSS 更容易实现这一点。在每个样式组件中,您都可以访问主题对象,例如,为每个输入指定 6px 的边框半径。

主题化的价值最好通过再次调整之前的组件来描述。我们可以通过以下方式向我们的应用程序添加主题:

import styled, {ThemeProvider} from 'styled-components'
const theme = {
    borderRadiusBlock: '6px',
}
const App = () =>
    <ThemeProvider theme={theme}>
        <StyledTextBlock isBold>
        I am a pretty text block
        </StyledTextBlock>
    </ThemeProvider>

您可以在样式化组件中像这样实现它。正如您在此处看到的,您可以直接访问主题对象并从集中位置调整应用程序的整个样式。

const StyledTextBlock = styled.div(({isBold, theme}) => `
    color: red;
    font-size: 16px;
    font-weight: ${isBold ? 'bold' : 'normal'};
    border: 2px solid black;
    border-radius: ${theme.borderRadiusBlock};
`);

尽管如此,总有一些事情需要考虑

styled-components 的优点让每个 javascript 开发人员都感到高兴,但仍然有一些问题需要克服。下面的论点并不是真正不选择样式组件的理由。这只是一个轻微的刺激,您必须习惯:包装组件可能会导致开销。

在重用大量组件的大型应用程序中,您经常需要对其他元素进行轻微调整。如果您重用样式组件,则非常容易,如下例所示:

const StyledButton = styled.button`
  display: inline-block;
  color: black;
`;

const RedButton = styled(StyledButton)`
  color: red;
  border-color: red;
`;

在前面的示例中,您看到有两个单独的按钮,其中一个红色按钮覆盖了已设置样式的按钮的样式。只要您尝试覆盖的元素也是样式化组件(或本机 React 元素),这总是可能的。如果你想覆盖一个不是样式组件的组件,你只能通过向组件添加 className 属性来实现,直到到达原生 React 元素:

const Link = ({ className, children }) => (
  <a className={className}>
    {children}
  </a>
);

const StyledLink = styled(Link)`
  color: black;
  font-weight: bold;
`;

但是,您也很可能使用的组件库中并未将 className 添加到每个组件中。例如,如果您使用外部库中的表单,但您不喜欢输入字段周围的填充。那么就无法避免使用包装组件。

想象一下您正在使用以下组件:

 const SomeComponentWithInput = () => (
    <div>
        <input />
    </div>
);

但是如果你想要红色边框怎么办?那么您不能通过简单地将 SomeComponentWithInput 放入样式对象中来做到这一点。在这种情况下,您可以将该组件包装在另一个样式化的组件中,在其中尝试访问您想要设置样式的组件。例如:

Import SomeComponentWithInput from ‘component-library’;

const SomeWrapper = styled.div`
    input {
        border-color: red
    }
`;

const App = () =>
    <SomeWrapper>
        <SomeComponentWithInput/>
    </SomeWrapper>

因为您可以访问每个子组件中的元素,所以您在覆盖其他样式方面仍然具有很大的灵活性。就像使用常规 CSS 一样,您可以使用类名或 id 等内容访问其他元素,但您也可以调用其他样式组件。想象一下,您想要调用一个具有子组件的组件,该子组件是样式化组件,那么您可以执行以下操作:

const StyledInput = styled.input`
    border-color: green
`;
// this component has a styled component StyledInput as Child
const SomeComponentWithInput = () => (
    <div>
        <StyledInput />
    </div>
);

然后你可以用包装器以这种方式到达它:

const SomeWrapper = styled.div`
    ${StyledInput} {
        border-color: red
    }
`;

使用这些包装器的缺点是您的代码库可能会变得复杂。样式化组件的一个优点是,您可以立即看到样式的来源,但使用包装器会失去其价值。除此之外,额外的包装 div 可能会导致测试发生变化,并使调试变得更加困难。

还要将性能视为可能的缺点。
如果不提及可能对用户体验产生负面影响的轻微性能问题,本文就不能结束。因为 styled-components 是一种 css-in-js 方法,所以所有内容都是用 javascript 编写的,这当然会增加 javascript 执行时间和包大小。这会对应用程序的初始加载时间产生负面影响。您也无法利用缓存所能带来的性能提升。经典 CSS 文件可以被缓存,但对于样式化组件则无法做到这一点,因为没有 CSS 文件。

结论

考虑到性能问题,您是否还应该迁移 React 应用程序?即使您已经使用 CSS 模块或任何其他解决方案(例如 Tailwind 或 PostCSS)构建了它?或许。我个人认为优点极大地弥补了可能的缺点,尤其是作为一个 javascript 开发人员。除此之外,主题的易用性确实有利于与用户体验设计师的协作。但您是否应该迁移仍然在很大程度上取决于其他因素,例如品味、项目范围以及您或您的团队成员的现有知识。始终仔细考虑您的样式工具,但选择样式组件肯定会让您作为 React 开发人员的生活更加愉快。

我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=5vbhp91f157x
THE END
喜欢就支持一下吧
点赞10 分享
评论 抢沙发

请登录后发表评论

    请登录后查看评论内容