回到2013年,React凭空出世。可是在那时,咱们会想,oh shit! 咱们好不容易分离了HTML/CSS/JS, 为何出现了JSX,咱们又须要把HTML和JS耦合在一块儿?React 创造了 HTML in JS. 在React中,咱们知道,一切即组件。那既然HTML能在js里写,为何咱们不把CSS也一块儿写呢?这样不才是一个真正的组件吗?javascript
Styled-components就是为React而生的,它是CSS in JS的下一代解决方案。以往咱们想要作到css scope都须要在webpack中各类配置,或者使用js的解决方案。而styled-components你只须要import styled from 'styled-components';
便可。css
甚至React完美的结合,不只是从TagName上,还有Props上。使咱们的代码有更好的语义化,可维护性更强,效率更高。固然咱们无需考虑它的学习成本,只要你用过CSS或者SASS均可以马上上手,由于它自己就是一种超集的存在。html
接下来,我会逐步的介绍一些这段时间以来,我很是喜欢的独有的特性。
const Button = styled.button` background: #abcdef; border-radius: 3px; border: none; color: white; `; console.log(Button); //styled component console.log(new Button()); // react component export default CustomButton extends React.component { render() { return <Button {...props} /> } }
styled-components 用了 tagged template语法,直接为咱们编写样式建立组件。
styled-components继承样式有两种写法以下java
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 权重覆盖。不推荐react
固然,还有一种有趣的“继承” withComponent
,咱们能够利用withComponent改变渲染的标签webpack
const Li = styled.li` color:#abcdef; `; const A = Li.withComponent('a'); // 将会渲染a标签
编译后他们会使用不一样的className,这对咱们想用同个样式,可是不一样标签很是有用。git
这里所说的样式覆盖,主要是一些交互上的行为(hover, active)覆盖。其实组件继承也算是覆盖的一种。
以往咱们的覆盖写法以下:es6
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进行引用,从而覆盖样式,以下github
const Icon = styled.span` color: red; `; const ListItem = styled.li` &:hover ${Icon} { color: green; } `;
这依旧是咱们过去的思路来覆盖样式,只是咱们把选择器直接使用styled
组件引用罢了。拥有这样的接口,就更加让咱们无需去思考须要给组件取什么className或者id,从而达到覆盖样式的作法。然而还有我最喜欢的另一种写法。web
TIPS:组件的引用必须是styled-components包装后的组件,直接是react的会报错
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呢?咱们有一个简单的技巧。好比使用了Material-UI,若是咱们须要基于它拓展咱们本身的组件,而且须要样式。
const ThemeProvider: React.SFC<ThemeProviderProps> = ({ themeName, children }) => { const theme = themes[themeName]; return ( <StyledThemeProvider theme={theme}> <MuiThemeProvider theme={theme}> {React.Children.only(children)} </MuiThemeProvider> </StyledThemeProvider> ); };
以后只须要把咱们须要调用的组件使用styled-components提供的withTheme
包装一下咱们的组件来获取咱们的theme。
这样既能够在咱们的styled-components里取到theme,material里也能够了。
以上就是咱们全部的技巧了, 看了这么多有意思的黑科技,难道你还不爱上styled-components吗?
我的网站 http://www.meckodo
Github: https://github.com/MeCKodo