问题的起因
最近需要实现这么一个功能,通过拖动来改变窗口左侧的文件列表栏的宽度。我选择了用
styled-components
来实现这个功能,并写了如下的样式组件,其中将边栏当前的宽度
width
作为属性传入。
1 | const StyledFileList = styled.div<{ width: number }>` |
但是当我快速拖动边栏时,width
变化得非常频繁,在控制台中展示了如下的 Warning。
大意是仅为这一个组件就生成了超过 200 个
class。利用开发者工具的查找元素,改变 width
时可以观察到元素上的 class 名称一直在变化。
1 | <div width="270" class="sc-bdvvtL ckAtiw"></div> |
可以确定 styled-components
给每一个不同的
width
属性都生成了一个 class。如果在 html 中搜索相应的
class 名称(如上面的代码中是 ckAtiw
和
bBcytR
),可以在 <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 | --your-awesome-color: darkcyan; |
这一行文字就是应用了上面的 CSS,你可以在控制台中修改样式并观察变化。
改写原代码
对于之前的边栏组件,我们可以换一个写法来解决,不再使用
props
来传入宽度,而是使用 CSS 变量,组件代码如下:
1 | <StyledFileList |
此时再改变左侧边栏的宽度,可发现元素的 class 名称是固定的,只有 style 在变化。
1 | <div class="sc-bdvvtL jGeOyv" style="--width:210px;"></div> |
如果检查 <head>
中的内容,会看到在
<style>
标签中相应的样式内容也只出现了一次,从而解决了样式冗余的问题。
参考资料
The styled-components Happy Path Demystifying styled-components