2013年,React凭空出世。在那时,我们在想,我们好不容易分离了HTML、CSS、JS, 为什么出现了JSX? 我们又要把HTML和JS耦合在一起?React 创造了 HTML in JS, 在React中,我们知道,一切即组件。那既然HTML能在js里写,为什么我们不把CSS也一起写呢?这样不才是一个真正的组件吗? 而Styled-components就是为React而生,它是CSS in JS的下一代解决方案。 以往我们想要做到css scope都需要在webpack中进行各种配置,或者使用js的解决方案。 而styled-components只需要import styled from 'styled-components';即可。便能与React完美结合,不仅从TagName上,还有Props上。使代码有更好的语义化,可维护性更强,效率更高。而且还不需要增加额外的学习成本,只要用过CSS或者SASS都可以立刻上手,因为它本身就是一种超集的存在。 那styled-components 是什么? styled-components 是一个常用的 css in js 类库。和所有同类型的类库一样,通过 js 赋能解决了原生 css 所不具备的能力,比如变量、循环、函数等。 它与其他CSS预处理相比有什么优点? sass、less 等预处理可以解决部分 css 的局限性,但还是要学习新的语法,而且需要对其编译,其复杂的 webpack 配置也总是让开发者抵触。 如果有过sass、less经验的开发者,也能很快的切换到styled-components,因为大部分语法都类似,比如嵌套, 继承。styled-componens 很好的解决了学习成本与开发环境问题,很适合 React 技术栈 与React Native 的项目开发。 它解决了什么问题? className 的写法会让原本写css的写法十分难以接受,如果通过导入css的方式,会导致变量泄露成为全局,需要配置webpack让其模块化,以及上面提到的解决了原生 css 所不具备的能力,能够加速项目的快速开发。 既然,styled-components那么好,我们就开始动手去体验。接下来,我会逐步的介绍这段时间来,styled-components一些独有的特性,希望你会喜欢。 styled-components官方文档地址: https://www./docs 开胃菜const Button = styled.button` background: #abcdef; border-radius: 3px; border: none; color: white;`;console.log(Button);
继承styled-components继承样式有两种写法如下 const Button = styled.button` background: #abcdef; border-radius: 3px; border: none; color: white;`;const OtherButton1 = styled(button)``;const OtherButton2 = button.extend``; // 老的写法,不推荐,未来会被废弃 写法一的继承,仅仅只会创建不一样的css rule,而第二种写法会复制一遍base component的css rule,然后在添加不一样的进行css 权重覆盖。不推荐 当然,还有一种有趣的“继承” withComponent,我们可以利用withComponent改变渲染的标签 const Li = styled.li` color:#abcdef;`;const A = Li.withComponent('a'); // 将会渲染a标签 编译后他们会使用不同的className,这对我们想用同个样式,但是不同标签非常有用。 样式覆盖
以往我们的覆盖写法如下: const ListItem = styled.li` padding: 0; height: 48px; &.left-item-focus { .left-link { background: ${props => props.color}; } } &:hover { .left-icon { color: #9e9e9e; // 500 } }`; 而在styled中,我们可以使用styled-components 组件方式对我们的DOM进行引用,从而覆盖样式,如下 const Icon = styled.span` color: red;`;const ListItem = styled.li` &:hover ${Icon} { color: green; }`; 这依旧是我们过去的思路来覆盖样式,只是我们把选择器直接使用styled组件引用罢了。拥有这样的接口,就更加让我们无需去思考需要给组件取什么className或者id,从而达到覆盖样式的做法。然而还有我最喜欢的另外一种写法。
const ListItem = styled.li``;const Icon = styled.span` color: red; ${ListItem}:hover & { // & 代表icon组件 color: green; }`; 这段代码实现的是一样的功能,只是我们思路转换了一下。可以发现这样的代码更加没有侵入性。更加符合开放封闭原则,当我们不需要这个Icon组件时,直接把这个Icon删除即可,我们不用去父组件里寻找与该组件有关的样式,不容易造成样式污染。突然觉得眼前一亮,有木有! 当然这种“子组件引用父级”的功能,还有更加广泛的引用。你可以选择该DOM任何parent,再对自己进行样式的覆盖。如下: const Icon = styled.span` color: red; html.ie-8 & { // fuck ie8 color: blue; } body.xxx & { color: green; }`; 当任何父级带有class都会覆盖Icon的样式。这种“子组件引用父级”的功能也是我最喜欢的功能没有之一。 在上面可以看见我们大量使用了&作为选择器,而&还有另外的技巧。 const Example = styled.li` color: red; & { color:blue; } && { color: green; }`; 大家可以猜猜,这最终会渲染成什么? li class='sc-gzVnrw fmpfVE'>li> 最终会编译成如下class,但是我们的一个&就代表一个class权重也就是说我们最后会渲染原谅色,原因是li被作用于了.fmpfVE.fmpfVE样式表。这个功能非常有用,比如在你使用第三方组件想要覆盖它的样式的时候,我们就可以加多个&来提高样式权重,从而覆盖第三方组件的样式 Theme关于Theme只想说一点,那就是结合第三方组件应该如何传入Theme呢?我们有一个简单的技巧。比如使用了Material-UI,如果我们需要基于它拓展我们自己的组件,并且需要样式。 const ThemeProvider: React.SFC 之后只需要把我们需要调用的组件使用styled-components提供的withTheme包装一下我们的组件来获取我们的theme。 这样既可以在我们的styled-components里取到theme,material里也可以了。
本文完~ 码字不容易,喜欢我,请打赏我一杯咖啡,让我创作更好的内容 ▲长按赞赏码即可打赏我
|
|