脱酥制的风格组件

2021-06-23 03:35:08

不知何故,使用一个模糊的半弦半函数语法,该工具能够采取一些任意CSS并将其分配给React组件,绕过CSS选择器We' vere始终使用。

喜欢这么多的Devs,我学会了如何使用样式组件,但没有真正了解引擎盖下发生了什么。

知道它是如何有用的。你不需要了解汽车的工作如何驾驶,但当你的车在路边打破时,它肯定有助于。

调试CSS在其自己的情况下很难,而无需添加一层工具魔法!通过搅拌风格组件,我们能够诊断和修复奇怪的CSS问题,这不太沮丧。

在这个博客帖子中,我们' ll弹出引擎盖,并通过建立自己的迷你克隆的💅风格组件来了解它是如何工作的。

样式组件附带了一系列辅助方法,每个方法对应于DOM节点。在那里' s h1,标题,按钮和数十个(它们甚至支持平线和路径等SVG元素!)。

使用晦涩的javaScript功能称为“标记的模板文字”,调用辅助方法。目前,您可以假装它的书面'

H1是样式对象上的辅助方法,我们将其称为单个参数,一个字符串。 这些辅助方法是小组件工厂。 每次叫他们时,我们都会获得一个全新的反应组成部分。 当我们运行const title = styled.h1(...)时,标题常量将被分配给我们的newcomponent组件。 当我们在我们的应用程序中呈现标题组件时,它' ll产生< h1> DOM节点。 我们传递给H1功能的样式参数呢? 它是如何使用的? 我们通过哈希样式提出一个唯一的类名,进入一个看似随机的字符串,如dkamqw或ioacve。 我们将新的CSS类注入页面,使用该散列字符串作为其名称,并包含STYLES字符串的所有CSS声明。 在反应中,它有条件地渲染一些JSX。 在这个例子中,我们只渲染我们的<包装器> 元素如果我们的Itemlist组件给出了一些项目:

函数itemlist({dements}){if(项目.length === 0){return"没有物品&#34 ;;返回(<包装器> {/ * extrited * /}< / wrapper>)} const包装= styled.ul` {[]} />);

您可以让您了解风格 - 组件并在这种情况下提供的CSS做任何事情。从未添加到DOM中的背景声明。

只要定义样式组件,我们会等待在将这些样式注入页面之前呈现组件之前才急切地生成CSS类。

这是一件好事!在较大的网站上,它并不少数千字节的未使用的CSS发送到浏览器。使用样式组件,您只需支付您呈现的CSS,而不是您写的CSS。

这作品的唯一原因是因为JavaScript有闭包。从styled.h1生成的每个组件都有自己的小范围,占据CSS字符串。当我们渲染包装器组件时,即使它' s秒/分钟/小时之后,它也可以独家访问我们为其编写的风格。

我们更有原因我们推迟CSS注射:由于内插样式。我们' ll涵盖了本文末尾的那些。

您可能想知道:CreateanDinjectCSSCLASS功能如何工作?我们是否可以从JS中真正生成新的CSS类?

我们可以!一种直接的方式是创建一个< style>标签,然后用原始CSS文本填充它:

这种方法有效,但它繁琐且慢慢地'一种更现代的方法是使用CSSOM,CSS版本的DOM。 CSSOM提供了一种友好的方法来使用JavaScript添加或删除CSS规则:

长期以来,通过CSSOM生成的样式' t在Chrome开发人员工具中编辑。如果你有史以来见过"灰色"由于这个限制,Devtools的风格,它' s:

然而,谢天谢地,这在Chrome 85中发生了变化。如果您' ref兴趣,Chrome团队写了一个博客文章,了解他们如何为devtools添加样式组件等css-in-js库的支持。

这是有效的,但我们需要更多的助手!我们需要按钮和链接和页脚和aside和marquees。

还有另一个问题。当我们' ll看到,风格可以直接调用为函数:

样式对象既是函数和对象。令人困惑的是,这是JavaScript中的完全有效的事情。我们可以这样做的东西:

让'更新我们的风格组件克隆以支持这些新要求。我们可以从功能规划中借一些想法,以使其成为可能。

此代码使用称为CURRYING的技术。它允许我们"预加载"标签参数。

如果你以前没有看到它,咖喱可以有点心态。但是它'在这种情况下有用,因为它允许我们轻松创建许多速记辅助方法:

关于风格组件的最酷的一个最酷的东西是我们可以将它们与我们自己的自定义组件混合!

函数消息({儿童,...委托}){return(< p {...委托}>您收到了一条消息:{儿童}< / p>); consturemessage =风格(消息)`背景颜色:粉红色;`;< rgentmessage>我们' re' re' re'< / urgentmessage>);

乍一看,这似乎绝对是神奇的。我们如何将这些样式应用于我们的自定义组件?

关键是在道具代表团中。这里'我们是什么' d看看我们是否注销委托对象:

我们提出了唯一的类名(OKJQVF),并将标签变量(我们的消息组件)与ClassName Prop渲染。

如果我们将ClassName Prop应用于我们组件中的HTML节点,则这仅适用。以下赢得了'

通过委派消息接收到< p&gt的所有道具;元素渲染,我们解锁此模式。值得庆幸的是,许多第三方组件(例如,React-Router中的链接组件)按此惯例。

Const Button = STEDED.BUTTON`背景 - 颜色:透明;字体大小:2REM;`CONST PINKBUTTON =样式(按钮)`背景颜色:粉红色;`;渲染(< pinkbutton> Hello World< / pinkbutton>);

我曾经认为图书馆"合并"这些款式以某种方式,创建一个新的"巨型类"这包含了所有声明。但它实际上创造了两个不同的类。

我们在这个过程中的目标是确保PinkBut​​ton Styles"延伸"按钮样式。如果发生冲突,PinkBut​​ton应该获胜。

我们可以依靠CSS来为我们做努力工作!

在CSS中,有一个复杂的规则层次结构,管辖如何解决冲突。一个ID选择器#btn将针对类选择器赢取.btn。这又击败了标签选择器,按钮。

但在这种情况下,我们有两个课程!两个选择器,.abc123和.def456同样匹配。所以该算法返回到辅助规则。它根据样式表中定义的规则顺序。

一个重要的澄清:我们应用课程的顺序并不是。考虑此案:

您可能希望第一段将是红色的,第二段将是蓝色的。但这将是不正确的:这两个段都将是蓝色的。类属性中的类的顺序并不重要:

样式组件库非常注意,以确保以正确的顺序插入CSS规则,以确保正确应用样式。这是一个非琐碎的问题:我们在反应中进行各种动态事物,而且图书馆正在不断添加/删除类,同时确保保留了明智的顺序。

我们需要更新我们的代码,以便它应用两个类。我们可以将它们相结合:

当我们呈现PinkBut​​ton时,标签变量等于我们的按钮组件。 PinkBut​​ton将生成一个唯一的类名(def456),并将其作为ClassName GRONG到按钮。

如果你和这个过程混淆了,你'重新孤单;我们进入了递归的思维造型领域,风格组件呈现样式组件。正如我写这篇文章的那样,我绊倒了这一点,不得不花一分钟重新配置自己的理解。

但是这里的事情:完成这个aren的精确JS力学' t重要。那个' s的实施细节。重要的是你了解这些外卖:

样式组件确保以正确的顺序插入这些规则,以便PinkBut​​ton' S样式将覆盖按钮中的任何冲突。

我们几乎完成了创造了我们的最低可行风格组件克隆,但在我们的列表中有一个任务:。

有时,我们的CSS将取决于反应道具。例如,图像可能需要maxwidth prop:

const contentimage = styled.img`显示:块;边缘:8px;宽度:100%; max-width:$ {p => p.maxwidth};`;渲染(< contentimage alt ="带粉红色鞋带的跑步鞋和彩虹贴花" src =" /images/shoe.png" maxwidth =" 200px" />>>>>>> contentimage alt ="同一跑步鞋的特写镜头" src =" /images/shoe-closeup.png&# 34; />< />)

第一类SC-BDNXRM用于唯一标识呈现的反应组件(ContentiMage)。它不提供任何风格,我们可以忽略它的目的。

看似随机的类名称,JDSLG和Exyyy实际上是将应用的样式。当我们在不同的MaxWidth Prop中插入时,我们得到了一个不同的样式,因此生成了一个唯一的类。

这解释了为什么我们可以' t"预先生成的"课程!我们必须等到组件呈现在我们知道将应用CSS之前呈现,因为相同的样式.Button实例Won' t始终产生相同的样式。

插值ISN' t唯一可以自定义一个特定组件实例的样式的方法。我最喜欢的方式是使用CSS变量。它看起来像这样:

const contentimage = styled.img`显示:块;边缘:8px;宽度:100%; max-width:var( - max-width);`;渲染(< contentimage alt ="带粉红色鞋带的跑步鞋和彩虹贴花" src =" /图像/ shoe.png" style = {' - max-width&#39 ;:' 200px',} />< contentimage alt ="关闭-Up拍摄同样的跑鞋" src =" /&g> />)

如果我们检查HTML,我们会注意到两个元素共享相同的CSS类:

通过让现代CSS为我们做动态的东西,我们会产生更少的CSS。这也是潜在的性能胜利:当动态数据发生变化时,我们不需要生成一个全新的CSS类并将其附加到页面!

我在我的博客文章中写了关于这个模式(和许多人!)“风格组件快乐路径”。

标记的模板文字是狂野的,它会采取完全独立的博客文章来解释他们如何工作以及他们在这里做什么。

要知道的重要事项是,当组件渲染时,并习惯"填补空白"在我们的风格字符串中。

当我们渲染我们的组件时,Condicatestyles能够通过通过道具传递的数据来调用每个内插功能。最终,我们用普通的OL&#39离开了;字符串填充值。

当道具更改时,重复该过程,并生成一个新的CSS类。

这个博客帖子一直是旅程。也许比任何其他帖子给我所写的,这占据了一些非常奸诈的地形。这种东西并不容易包裹我们的思想。

如果这篇文章的部分' t对你有很大的意义,那个'好的!它可能需要有点渗滤。随着您继续使用风格组件,希望这篇文章中的想法变得清晰。

除了了解您的工具的实际好处,我希望这篇文章也有助于您了解风格组件团队已完成的内容。建立和维护开源软件永远不会轻松,它特别吸引在CSS-In-JS工具中,在整个类别令人争议的社区中。

如果您发现此帖子有用,您可能对别的东西感兴趣。 它' s为JavaScript开发人员的CSS。 它'是一个专门为js框架devs创建的全面的在线课程,他们发现CSS混淆或令人沮丧。 我们从第一个原则中确切了解CSS如何作为一种语言,构建一个可用于解决您遇到的每个布局挑战的强大精神模型。 我计划在今年9月推出课程。 您可以在官方网站上注册更新!