吴锴的博客

Life? Don't talk to me about life!

0%

一个 styled-components 的问题(props or css variables)

问题的起因

最近需要实现这么一个功能,通过拖动来改变窗口左侧的文件列表栏的宽度。我选择了用 styled-components 来实现这个功能,并写了如下的样式组件,其中将边栏当前的宽度 width 作为属性传入。

1
2
3
4
5
6
7
const StyledFileList = styled.div<{ width: number }>`
position: absolute;
top: 0;
left: 0;
width: ${props => props.width + 'px'};
height: 100%;
`;

但是当我快速拖动边栏时,width 变化得非常频繁,在控制台中展示了如下的 Warning。

控制台warning

大意是仅为这一个组件就生成了超过 200 个 class。利用开发者工具的查找元素,改变 width 时可以观察到元素上的 class 名称一直在变化。

1
2
3
<div width="270" class="sc-bdvvtL ckAtiw"></div>

<div width="271" class="sc-bdvvtL bBcytR"><div>

可以确定 styled-components 给每一个不同的 width 属性都生成了一个 class。如果在 html 中搜索相应的 class 名称(如上面的代码中是 ckAtiwbBcytR),可以在 <head><style> 标签中找到它们对应的样式内容,稍加比较就可以发现除了 width 以外的部分都是相同的。

styled-components处理样式的过程是这样的:属性改变 -> 重新生成样式 -> 插入到 <head> 中,这个过程如果重复很多次,会产生大量的 CSS 内容冗余,很有可能造成性能问题。而我们可以通过使用 CSS 变量来解决这个问题。

使用 CSS 变量

我是在这篇文章 The styled-components Happy Path 中学到了在 styled-components 中使用 CSS 变量(CSS variable)的技巧。

什么是 CSS 变量

CSS 变量是以 -- 开头的属性名称,它们的值可以是任何类型的值,使用 var(--your-variable-name) 来应用样式。

1
2
3
4
5
--your-awesome-color: darkcyan;
color: var(--your-awesome-color);

--this-padding: 20px;
padding-left: var(--this-padding);


这一行文字就是应用了上面的 CSS,你可以在控制台中修改样式并观察变化。

改写原代码

对于之前的边栏组件,我们可以换一个写法来解决,不再使用 props 来传入宽度,而是使用 CSS 变量,组件代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<StyledFileList
// 这里定义了 --width 这个 CSS 变量,width 是一个 number
style={{ '--width': width + 'px'} as CSSProperties}
>

const StyledFileList = styled.div`
position: absolute;
top: 0;
left: 0;
// 这里应用了 CSS 变量
width: var(--width);
height: 100%;
`;

此时再改变左侧边栏的宽度,可发现元素的 class 名称是固定的,只有 style 在变化。

1
2
3
<div class="sc-bdvvtL jGeOyv" style="--width:210px;"></div>

<div class="sc-bdvvtL jGeOyv" style="--width:250px;"></div>

CSS变量样式

如果检查 <head> 中的内容,会看到在 <style> 标签中相应的样式内容也只出现了一次,从而解决了样式冗余的问题。

参考资料

The styled-components Happy Path
Demystifying styled-components

欢迎关注我的其它发布渠道