选择完全适合您需求的样式模块就像选择 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
请登录后查看评论内容