CSS in JS之styled-components

【高频考点精讲】CSS-in-JS方案对比:Styled-components vs Emotion CSS-in-JS已经成为了现代前端开发的标配。Styled-components和Emotion各有千秋,没有绝对的好坏。我的建议是:个人项目按喜好选,企业项目看团队习惯和性能需求。下次遇到样式难题时,不妨想想全栈老李今天讲的这些对比点。如果你有特别的使用心得,也欢迎在评论区分享讨论! 阅读详情

代码已经关联到github: 链接地址 觉得不错可以顺手点个star,这里会持续分享自己的开发经验(:

我们都知道,JSX是JS语法的扩展,增加了对HTML语法的支持,那距离all in js就只差一个CSS语法支持了,目前实现该功能的库比较出名的有60+,感兴趣的可以自己查看:css-in-js。
下面要介绍的就是其中之一的styled-components。
​

简介

styled-components应该可以说CSS-in-JS最热门的一个库了,到目前为止github的star数已经超过了34k。
通过styled-components,你可以使用ES6的 标签模板字符串 语法在Component中定义一系列CSS属性,当该组件的JS代码被解析执行的时候,styled-components会动态生成一个CSS选择器,并把对应的CSS样式通过style标签的形式插入到head标签里面。
动态生成的CSS选择器会有一小段哈希值来保证全局唯一性来避免样式发生冲突。
​

​

Hello World

​

下面我们简单来了解下其写法:

const Title = styled.h1`
  font-size: 1.5em;
  text-align: center;
  color: palevioletred;
`;


const Wrapper = styled.section`
  padding: 4em;
  background: papayawhip;
`;

render(<Wrapper>
    <Title>Hello World</Title>
  </Wrapper>
}

编译后的样子:
​
在这里插入图片描述

其特点是什么?
​

  • 相当与定义了一个空的组件
  • 每一段样式必须绑定到一个组件上
  • 语法与CSS完全一样
  • 模板字符串编写
  • …

原理

基于5.3.1版本代码,下面简单解释其原理。
​

语法解释

从其写法分析,代码的可以拆解为styled.xx和后面的模板字符串。
​

前者可以理解成一个styled-components定义的函数,eg:

const styled = (tag) => {
	//...
};

domElements.forEach(domElement => {
  styled[domElement] = styled(domElement);
});

那后面的模板字符串,函数是怎么去解析的呢?这就不得不说模板字符串的一个功能带标签的模板字符串,该功能可以用函数解析模板字符串,eg:

function tag(strings,...keys){
  console.log('strings:', strings)
  console.log('keys:',keys)
}

tag`
	color:red;
	background:${props => props.bgcolor};
`

//strings: ["\n\tcolor:red;\n\tbackground:", ";\n", raw:["\n\tcolor:red;\n\tbackground:", ";\n"]]
//keys: [props => props.bgcolor]

得到原始字符串和占位符数据,这样就可以组装好css模板,渲染的时候根据传入值渲染即可。

组件创建过程
  1. 生成唯一id

根据参数和父组件生成,比如上面编译后的sc-jlyJG。

const styledComponentId = generateId(options.displayName, options.parentComponentId)
  1. 对模板字符串解析得到样式,在head 中插入一个 style 节点并将样式注入,返回 className,比如之前编译后的eFyTid。下面简单描述这一过程:
// 构造className 
const generatedClassName = generateName(cssStatic >>> 0);

//构造style节点并获得
const style = document.createElement('style');
style.setAttribute(SC_ATTR, SC_ATTR_ACTIVE);
style.setAttribute(SC_ATTR_VERSION, SC_VERSION);
//...省略上一个style标签位置查找
// Avoid Edge bug where empty style elements don't create sheets
style.appendChild(document.createTextNode(''));
//根据传入的节点获得sheet
this.sheet = style.sheet //getSheet(style)

//最后插入css
this.sheet.insertRule(rule, index);

​

  1. 解析组件的其他props和attr得到新的元素参数propsForElement
  const computedProps = attrs !== props ? { ...props, ...attrs } : props;
  const propsForElement = {};

  for (const key in computedProps) {
    if (
      shouldForwardProp
        ? shouldForwardProp(key, validAttr, elementToBeCreated)
        : isTargetTag
        ? validAttr(key)
        : true
    ) {
      // Don't pass through non HTML tags through to HTML elements
      propsForElement[key] = computedProps[key];
    }
  }
  1. 最后根据propsForElement和className生成组件
propsForElement.className = Array.prototype
  .concat(
  styledComponentId,
  generatedClassName !== styledComponentId ? generatedClassName : null,
  props.className,
  attrs.className
)
  .filter(Boolean)
  .join(' ');

// elementToBeCreated生成过程被省略了,该参数是一个元素标签或者是一个react组件
return createElement(elementToBeCreated, propsForElement);

​

基础使用指南

基于Props设置样式

styled定义的组件可以接受props参数,根据不同的参数设置样式。

const Button = styled.button`
  background: ${props => props.primary ? "palevioletred" : "white"};
  color: ${props => props.primary ? "white" : "palevioletred"};

  font-size: 1em;
  margin: 1em;
  padding: 0.25em 1em;
  border: 2px solid palevioletred;
  border-radius: 3px;
`;

render(
  <div>
    <Button>Normal</Button>
    <Button primary>Primary</Button>
  </div>
);

继承样式

可以在继承一个已有组件的基础上生成一个新的组件,可以覆盖和新增样式。

const Button = styled.button`
  background: white;
  color: palevioletred;
  font-size: 1em;
  margin: 1em;
  padding: 0.25em 1em;
  border: 2px solid palevioletred;
  border-radius: 3px;
`;

const PrimaryButton = styled(Button)`
	background: palevioletred;
  color: white;
`

render(
  <div>
    <Button>Normal</Button>
    <PrimaryButton>Primary</Button>
  </div>
);

传递HTML属性

我们都知道html元素有很多属性,比如input 的 type、readonly和onChange 等属性。

const Input = styled.input`
  padding: 0.5em;
  margin: 0.5em;
  background: papayawhip;
  border: none;
`;

const handleChanged = (e) => {
	console.log('input changed:',e.target.value)
}

render(
  <Input defaultValue="default val" type="email" onChange={handleChanged}/>
)

组件中维护其他HTML属性

styled-components 同时支持为组件传入 html 元素的其他属性,比如为 input 元素指定一个 type 属性,我们可以使用 attrs关键字来实现。
​

使用过程中,我们可以使用静态属性,也可以使用props参数设置:

const Password = styled.input.attrs({
  type: 'password',
  placeholder:${props=>props.placeholder?props.placeholder:''}
})`
  color: palevioletred;
  font-size: 1em;
  border: 2px solid palevioletred;
  border-radius: 3px;
`;

​

在实际开发中,这个方法还有一个有用处,用来引用第三方类库的 css 样式:

const Input = styled.input.attrs({
  className: 'my-input',
})`
  color: palevioletred;
  font-size: 1em;
  border: 2px solid palevioletred;
  border-radius: 3px;
`;

与className和css框架搭配使用

可以与组件的className搭配使用,当然前提className是不会混淆的命名

const Wrapper = styled.section`
  padding: 4em;
  background: papayawhip;
	& > .my-h1{
		font-size: 1.5em;
    text-align: center;
    color: palevioletred;
	}
`;

render(
   <Wrapper>
    <h1 className={'my-h1'}>My H1</h1>
  </Wrapper>
)

同样的也兼容less等css框架使用。

import * as styles from './index.less'

const Wrapper = styled.section`
  padding: 4em;
  background: papayawhip;
`;

render(
   <Wrapper>
    <h1 className={styles['my-h1']}>My H1</h1>
  </Wrapper>
)

& 关键字

与less 中类似,& 在语法中代表自身选择器,我们上一节就使用了该用法。

const Wrapper = styled.section`
  padding: 4em;
  background: papayawhip;
	& > .my-h1{
		font-size: 1.5em;
    text-align: center;
    color: palevioletred;
	}
`;

除了这种用法,他还可以用来增加样式的权重

const Example = styled.li`
    color: red; 
    & {
        color:blue;
    }
    
    && {
        color: green;
    }
`;

动画

styled-components 同样对 css 动画中的 @keyframe 做了很好的支持。

const rotate = styled.keyframes`
  from {
    transform: rotate(0deg);
  }

  to {
    transform: rotate(360deg);
  }
`;

const styles = styled.css`
  animation: ${rotate} 2s linear infinite;
`

const Rotate = styled.div`
	${styles};
  display: inline-block;
  padding: 2rem 1rem;
  font-size: 1.2rem;
`;

render(
  <Rotate>&lt; 💅🏾 &gt;</Rotate>
);

ref

通过传递ref属性,可以获得组件的元素节点。

const Input = styled.input.attrs({
  className: 'my-input',
})`
  color: palevioletred;
  font-size: 1em;
  border: 2px solid palevioletred;
  border-radius: 3px;
`;

const inputRef = React.useRef();
render(
  <Input ref={inputRef}/>
);

组件嵌套选择器用法

如果两个组件定义的作用域一致,则可以直接嵌套使用选择器。

const Wrapper = styled.section`
  padding: 4em;
  background: papayawhip;
`;
const Title = styled.h1`
  font-size: 1.5em;
  text-align: center;
  color: palevioletred;
`;
const SubTitle = styled.span`
  text-align: center;
	color: grey;

	${Title}:hover &{
			color: red;
	}
`
render(
  <>
  <Wrapper>
    <Title>
  		Hello World 
  		<SubTitle> yes!</SubTitle>
  	</Title>
  </Wrapper>
  <SubTitle> no...</SubTitle>
  </>
}

​

​

对象样式定义

如果样式都是一个对象类型,那也可以之间舍弃模板字符串,直接使用对象定义的方式定义样式。

const Box = styled.div({
  background: 'palevioletred',
  height: '50px',
  width: '50px'
});

const PropsBox = styled.div(props => ({
  background: props.background,
  height: '50px',
  width: '50px'
}));

render(
  <div>
    <Box />
    <PropsBox background="blue" />
  </div>
);

其他

  1. 支持ts
  2. 支持单测
  3. 语法检测
  4. 语法高亮​

优劣

优势

  1. 标准CSS语法
  2. 自动注入 CSS

styled-components 根据页面上呈现的组件,自动注入它们的样式,减少多余代码的引入。

  1. 唯一类名

styled-components 为您的样式生成唯一的类名,不用担心重复或拼写错误。

  1. 设置动态样式非常简单

根据组件的 props 或全局主题调整组件的样式简单直观,无需手动管理数十个类。

  1. 维护简单

不必在不同的文件中寻找影响组件的样式。

  1. 自动添加浏览器前缀

我们只需要编写一次css,sc在渲染的时候根据浏览器自动帮我们增加前缀。

劣势

  1. 学习成本高。适合已经有一定开发经验的人使用
  2. 代码可读性差。动态生成的唯一类名阅读困难,不能写z如果是需要开放类组件库适用性差。
  3. 冗余度高。使用props动态生成样式时,不同的props值生成的样式会一直存在。
  4. 性能
    1. 运行时动态生成css
    2. 运行时包高达15.4kb

​

参考

官网​
CSS in JS的好与坏
styled-components 运行原理​

大数据安全 | 期末复习(上)| 补档 大数据定义:无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合,是需要新处理模式才能具有更强的决策力、洞察发现力和流程优化能力的海量、高增长率和多样化的信息资产。 阅读详情

相关推荐

Unity抖音小游戏上架实战:从零到一,详解流程与避坑指南

本文详细介绍了Unity抖音小游戏上架的全流程,包括环境准备、SDK集成、开发者账号注册、软著申请、打包提交流程及常见问题解决方案。重点解析了抖音小游戏平台特有的配置细节和避坑技巧,帮助开发者高效完成游戏上架并优化用户体验。

weixin_33704234的博客 261

Styled-Component

Styled Components 是一个使用CSS-in-JS技术实现的样式组件库,它是一个为React和React Native设计的库。它允许我们在应用中使用JavaScript和CSS混合起来编写样式级组件。并且它是支持Sass的,不需要添加任何库。

weixin_42478537的博客 6102

大疆sdkV4以及V5webrtc推流

webrtcSDK中要用它的VideoCapturer来初始化推流 ViewdoCapturer是一个接口我们继承它 然后重建创建文件CapturerAircraft.java文件。CameraUtil.java这个是我们用来创建CapturerAircraft的一个工具。除了CapturerAircraft这个文件不一样外其他都是一样的。PlayBodyBean.java这个是我们的配置文件。下面的有个代码块第一个是v4的 第二个是v5的。接着我们来创建几个推流用到的webrtc工具。

weixin_41624865的博客 1188

做react项目遇到的bug,axios返回Promise对象问题,styled-components结合ts问题, 传入组件的函数用useCallback优化性能

1 axios返回promise对象问题 打印了一下data,是个对象没问题,但是,async返回来的是一个Promise对象,即使你手动写了reutrn data,返回一个对象,async也是会包裹成一个Promise对象返回。故,你在外层想拿到数据时,有两种方法: (1) 使用Promise对象的.then方法来获取数据。 (2) 因为返回来的是一个Promise对象,故在外层可以继续使用async await去获取。 如果不用async await ,直接LET DATA = 去获取,会拿到一个处

lin_fightin的博客 2993

从零到一:手把手教你用YonBuilder for NCC搭建NC Cloud 2021.11开发环境(含避坑指南)

本文详细指导如何使用YonBuilder for NCC搭建NC Cloud 2021.11开发环境,涵盖硬件要求、软件安装、YonBuilder配置及常见故障排除。特别提供避坑指南,帮助开发者快速上手NCC开发,确保环境配置的原子化分解和开发思维的体系化建立。

weixin_42523326的博客 345

从硬件到软件:TSMaster报文过滤全链路配置指南(含同星设备适配)

本文详细介绍了TSMaster平台下CAN/LIN/FlexRay总线的报文过滤全链路配置指南,特别针对同星TC1016等硬件的兼容性进行实战演示。从硬件层预过滤到软件层可编程过滤,提供五维过滤体系构建方法,帮助工程师提升车载诊断与总线分析效率。重点解析混合总线过滤策略优化及诊断场景下的特殊过滤方案。

tensorflowjs6的博客 402

styled-components 库的用法介绍和实践总结

是一个流行的CSS-in-JS库, 它允许您在 JavaScript 中编写 CSS 样式,是CSS-in-JS方案中的一种实现方式。官方文档:官方文档Github:Github我们经常会有使用公共样式的场景,比如ellipsis来实现文字超长省略。这种场景非常多,没必要在每个地方都写一遍上面的这一段代码,这时候可以使用导出的css函数可以生成一个公共样式组件, 建议单独创建一个样式文件存放公共样式。我们创建一个// ......然后在Title.tsx。

u010844210的博客 3165

手把手教你用Arduino搭建惠斯通电桥:从原理到代码实现(附完整电路图)

本文详细介绍了如何利用Arduino搭建惠斯通电桥,从硬件选型、电路设计到代码实现和校准技巧,提供完整的电路图和实用代码示例。特别适合电子爱好者和创客学习高精度电阻测量技术,并扩展应用于应变片测量和温度监测等实际项目。

o4p5q6r7s的博客 401

styled-components库的原理,模板字符串调用函数

【日常记录】【JS】styled-components库的原理,模板字符串调用函数

呆呆狗 592

【深度学习】基于BERT模型的情感分析(附实战完整代码+数据集)

情感分类是一个快速发展的研究领域,尽管众多模型和数据集在二分类任务中显示出很高的准确性,但细粒度的情感分类任务仍然是一个很大改进空间的领域。分析SST-5数据集,Munikar等人的先前工作表明,嵌入工具BERT允许使用简单的模型来实现最新的准确性。

aaaa_hsjsueu的博客 2万+

东方财富网股票API逆向分析:手把手教你破解动态参数(2024最新版)

本文详细解析了2024年东方财富网股票API的动态参数生成机制,包括回调函数、身份验证和时效控制参数的逆向工程方法。通过实战代码演示,帮助开发者破解动态参数,实现高效稳定的股票数据爬取,适用于金融数据分析和量化交易场景。

weixin_29091105的博客 1026

React--》掌握styled-components重塑React样式管理

想象一下,如果你的React组件不仅能自描述其逻辑,还能直接声明自己的样式,这种“所见即所得”的编程体验是不是让人心动不已?styled-components正是这样一把钥匙,它彻底颠覆了我们对React样式管理的传统认知,让样式与组件的结合变得如此自然与和谐。

ztK63LrD的博客 3138

机器学习(ML)在材料领域应用

机器学习作为一种兼顾开发效率以及开发成本的方法,已经逐渐应用于材料发现、结构分析、性质预测、反向设计等多个领域,并且在材料学研究中展现出惊人的潜力。传统的发现新材料的方法,如经验试错法和基于密度泛函理论(DFT)的方法,往往需要较长的研发周期,成本高、效率低,已经不能很好的适应如今需求量激增的材料学领域 ...

W5632DE的博客 3716

【styled-components】css-in-js 热门库

文章目录简介基本使用样式继承属性传递 简介 css-in-js 是一种技术,而不是一个具体的库的实现。简单来说 css-in-js 就是将应用的 css 样式写在 JavaScript 文件里面,而不是独立为一些 css、scss或less这类的文件,这样你就可以在 css 中使用一些属于 js 的如模块声明、变量定义、函数调用和条件判断等语言特性来提供灵活的可扩展的样式定义。css-in-js 在react社区的热度是最高的,这是因为 react 本身不会管用户怎么去为组件定义样式问题,而vue有属于框

qq_45677671的博客 2754

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

CSS-in-JS(含样式化组件 styled-components)

CSS-in-JS 是一种的技术范式,它不是某个具体的库,而是一类解决方案的统称。传统开发中,CSS、JS、HTML 是分离的,而 CSS-in-JS 让样式成为 JS 的一部分,能利用 JS 的编程能力(如变量、条件判断、函数、模块化)来管理样式,最终通过运行时或编译时将 JS 中的样式转换成浏览器可识别的 CSS。

朝阳39的博客 1126

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

【JavaScript Styled Components 实战宝典】:掌握5大核心技巧,打造可维护的CSS-in-JS项目

掌握JavaScript Styled Components 示例的正确用法,解决CSS命名冲突与样式维护难题。涵盖主题定制、响应式设计、动态样式等5大核心技巧,适用于React项目开发。提升组件可复用性与团队协作效率,打造高内聚的CSS-in-JS架构,值得收藏。

InstrIsle的博客 408

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

CSS in JS 的演进:Styled Components, Emotion 等的对比与选择

为了解决这些痛点,CSS-in-JS 应运而生,它允许开发者直接在 JavaScript 代码中编写 CSS,并将其与组件逻辑紧密结合,带来了前所未有的样式管理体验。CSS Modules + CSS-in-JS: 可以逐步将组件的样式迁移到 CSS-in-JS,实现新组件使用 CSS-in-JS,旧组件保持 CSS Modules。Linaria: 一个“零运行时”的 CSS-in-JS 库,它会在构建时将 CSS 提取到单独的文件中,并将类名注入到 JS 中,几乎没有运行时开销。

2501_92954090的博客 1267

CSS-in-JS也要被检查:css-checker的Styled Components检查(-styled)上手演示

**css-checker** 是一款几秒内找出重复与高相似 CSS 类的检查工具,而它的 `-styled` 参数还能把 CSS-in-JS(Styled Components)写入 `.js/.ts` 文件中的样式一并纳入检查。本文面向新手,演示如何安装 css-checker,并用一条命令扫描项目里的 Styled Components,快速定位冗余样式。 ## 为什么 CSS-in-JS

gitblog_00263的博客 451

react——css-in-js——styled-components库——定义样式——样式继承——属性传递

react——css-in-js——styled-components库——定义样式——样式继承——属性传递

阿牛哥的博客 390

使用styled-components实现CSS in JS

前面的话   使用jsx语法可以实现HTML in JS,使用svgr可以实现svg in JS,使用styled-components可以实现CSS in JS。这样,使用react开发,就变成了使...

whiteGay的博客 214

10个你必须掌握的CSS-in-JS库:从styled-components到emotion

在现代前端开发中,CSS-in-JS技术已经成为React生态系统的重要组成部分。这种革命性的样式方案让开发者能够在JavaScript中编写CSS,实现样式的组件化、动态化和作用域隔离。本文将为你详细介绍10个最值得掌握的CSS-in-JS库,帮助你选择最适合项目的样式解决方案。💫 ## 什么是CSS-in-JS技术? CSS-in-JS是一种将CSS样式直接写入JavaScript代码中

gitblog_01003的博客 458

从一个按钮实例入门CSS in JS之styled-components

前言 最近接手一个react项目,项目中使用的 CSS in JS方案来实现CSS模块化,它使用的包是styled-components 我以前的项目Vue居多的,Vue是很简单的通过scoped就可以实现模块化CSS,当然也在项目中用过CSS Modules方案,但CSS in JS还是第一次接触

cmdos的专栏 45

React Email与CSS-in-JS:Styled Components的邮件实践

在现代Web开发中,CSS-in-JS方案如Styled Components已成为主流,但在邮件开发领域却面临着独特的挑战。邮件客户端对CSS的支持程度参差不齐,Gmail、Outlook、Apple Mail等主流客户端各有不同的渲染限制: ```mermaid flowchart TD A[邮件样式开发] --> B{CSS支持级别} B --> C[现代客户端Ap...

gitblog_00923的博客 913

如何使用 lint-staged 自动检查 CSS-in-JS:styled-components 完整配置指南

lint-staged 是一个强大的工具,可以在 Git 提交前自动检查和修复暂存文件,帮助开发者在代码提交前发现并解决问题。本文将详细介绍如何使用 lint-staged 检查 CSS-in-JS 代码,特别是 styled-components 方案,让你的样式代码质量提升一个台阶。 ## 为什么需要 lint-staged 检查 styled-components? 在现代前端开发中,C

gitblog_00190的博客 729

CSS in JS 的演进:Styled Components, Emotion 等的深度对比与技术选型指引

CSS in JS(JS中的CSS)应运而生,它将CSS与JavaScript紧密结合,允许开发者在JavaScript文件中直接编写样式,从而实现组件级别的样式封装、动态样式控制以及更优的样式管理。Emotion 同样是CSS in JS领域的重要力量,它在Styled Components的基础上,提供了更灵活的API和更优的性能优化方案。CSS in JS 的核心理念是通过JavaScript的力量,将CSS的声明、选择器、状态联动等逻辑,以更现代、更具编程性的方式融入到组件的生命周期中。

GEO_YScsn的博客 823
上一篇: JavaScript中的this指向全解析
下一篇: Win10值得推荐的软件,提升效率和桌面美观
Qssn丶
博客等级 码龄11年 88粉丝 113原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值