白话速述 styled-components 4.x 的使用

废话不多话,来上车!安装: npm install –save styled-components (或者 yarn add styled-components)简述使用:1、 创建全局的样式:首先创建一个JS文件,例如style.js ①:import { createGlobalStyle } from ‘styled-components’ // 引全局包 ②:export const GlobalStyle = createGlobalStylemargin:0// ``里面为项目需要的css内容 ③:在react组件内 把引入的 GlobalStyle 当做标签写入 class App extends Component { render() { return ( <GlobalStyle></GlobalStyle> ); } } 创建一个局部的样式①:import styled from ‘styled-components’; // 引局部包 ②:export const HeaderWrapper = styled.div //里面为项目需要的css内容 ③:在react组件内 把引入的 HeaderWrapper 当做标签写入 class App extends Component { render() { return ( <HeaderWrapper></HeaderWrapper> ); } } 3、类嵌套:(类似于less sass用法大同小异)列举个项目实例: export const SearchWrapper = styled.div position:relative; float:left; .iconfont{ position:absolute; };4、增加属性写法: 举例给A标签增加attrs属性: export const Logo = styled.a.attrs({ href:’/’ }) 5、 设置当前元素内指定的class类 &amp;.left{ float:left; } &amp;::placeholder{ color:#999; }6、 styled-components 传值写法: 样式内js文件用props去接收 export const RecommendItem = styled.div background: url(${(props) => props.imgUrl}); ; react组件内给样式JS文件传入需要的地址 &lt;RecommendItem imgUrl="http://xxxxx"/&gt;7、常见小坑: 引图片不要直接写行内样式,默认会转化为字符串,导致加载图片失败,可用如下方式: import logoPic from '../../statics/logo.png'; export const Logo = styled.a background:url(${logoPic}); `;整理不易,喜欢的话就顺手点个赞吧,您的赞会是我们继续分享的动力 ! ...

January 17, 2019 · 1 min · jiezi

Css in Js 一次实践

最近需要做一个表格组件,组件需求:指定行、列可以跨行、跨列行和行之间有分割线最终采用grid实现需求。实现的时候遇到一个问题,如果css和js分开写,css只能是定值,没有灵活性。所以考虑采用css in js的形式。关于css in js相关的概念介绍可以参考阮一峰老师的文章:css in js 介绍。在github上找了一下关于这方面的组件,发现styled components 非常不错,简单易上手,npm下载:npm i styled-components -S注意:React < 16 需要下载3.x.x版本的 根据文档先写一个简单的demo。可以看到,它的实现方式并不是传统的以对象的形式写样式,而是将需要添加样式的元素加到styled对象上,然后跟一个(``)反引号标签,在里面以正常的css格式写样式。然后返回一个组件,把组件替换原来的div即可。实现效果:html代码:css代码:刚才我们添加样式的元素是html元素,那么给组件添加样式可以么?实践一下:const H1 = ({ className }) => <h3 className={className}>我是App</h3>;const HH = styled.H1 font-size: 30px; color: red;;运行,报错:咋回事?原来styled不支持以 . 符号的形式为组件添加样式,需要以参数形式传递,修改上面代码const HH = styled(H1) font-size: 30px; color: red;;将H1组件以参数形式传递给styled,就可以了。想给元素添加伪元素样式,子元素样式可以么?没问题,styled components支持样式嵌套,按照类似Less或Scss的书写方式就可以了。const Container = styled.div width: 300px; max-width: 500px; min-width: 200px; transition: all 1s ease-in-out; background-color: rgba(240, 240, 240, 0.9); ::after { content: 'after'; display: table; color: blue; } span { color: green; };以上我们写的组件都是在Class外面,那我们要根据props设定样式怎么办?styled components同样支持在Class内生成组件,并接受props传递过来的值,这个props并不是我们的Class接收的props,它是添加样式的元素上的Props,意思就是class Demo { render(){ return <Styled name=“guoshi”></Styled> }}Demo.defaultProps = { age: 18}const Styled = styled.p color: ${props=&gt;{console.log(props)}} // {name: "guoshi",theme:{...}}如果想使用Class的props怎么办?看代码:generateStyle = () => { const {row, col, justify, data, prefixCls, showborder = true, rowgap = 0, colgap = 0} = this.props; const child = []; data.map((item,index)=> (item.colSpan || item.rowSpan) ? child.push({index:index+1,colSpan:item.colSpan, rowSpan:item.rowSpan}):null); const bordernone = []; for(let i = 0; i < row; i++) { bordernone.push(1 + i*col); } const UlContainer = styled.ul.attrs({className: prefixCls}) display: grid; grid-template-columns: ${()=&gt; { let arr = []; arr.length = col; return arr.fill('1fr').join(' '); }}; grid-template-rows: ${()=&gt; { let arr = []; arr.length = row; return arr.fill('1fr').join(' '); }}; grid-gap: ${rowgap} ${colgap} ; justify-items: ${()=&gt; justify || "center"}; ::before { display: none; } li { width: 100% !important; } ${ child.map(({index, colSpan, rowSpan}) =&gt; li:nth-child(${index}) { grid-column-start: ${index%col === 0 ? index : index%col}; grid-column-end: ${colSpan ? (colSpan+(index%col === 0 ? index : index%col)) : ((index%col === 0 ? index : index%col)+1)} grid-row-start: ${Math.ceil(index/col)}; grid-row-end: ${rowSpan ? rowSpan+Math.ceil(index/col) : Math.ceil(index/col)+1}; align-items: start; } ).join(' ') } li + li { border-left: 1px dashed rgba(0,0,0,0.3); } ${ bordernone.map(bordernoneindex=&gt; li:nth-child(${bordernoneindex}) { border-left: none; } ).join(' ') } ; return UlContainer; }提前把最后代码放出来了,styled.ul.attrs({})就是为元素添加额外的属性,比如className、placeholder等,从代码中可以看到,无论是Class的props还是元素自身传进来的props,styled都可以接收,你可以自定义任何你想实现的规则,更方便我们配置的灵活性。其实到这里,使用上没有任何问题了,关于keyframes等规则官网上都有demo,也非常容易实现。想尝试的小伙伴现在就可以码一遍。不过本章遗留了很多问题:styled.div & styled(div) 有什么区别模版字符串中的样式是怎么解析的?为什么可以嵌套?为什么会返回一个组件?下一章,我会根据styled componnets源码解答上述问题。最后,祝生活愉快。 ...

December 28, 2018 · 2 min · jiezi

五分钟 Styled-components 高级实用技巧

写在前面的废话回到2013年,React凭空出世。但是在那时,我们会想,oh shit! 我们好不容易分离了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都可以立刻上手,因为它本身就是一种超集的存在。接下来,我会逐步的介绍一些这段时间以来,我非常喜欢的独有的特性。开胃菜const Button = styled.button background: #abcdef; border-radius: 3px; border: none; color: white;;console.log(Button); //styled componentconsole.log(new Button()); // react component export default CustomButton extends React.component { render() { return <Button {…props} /> }}styled-components 用了tagged template语法,直接为我们编写样式创建组件。继承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,这对我们想用同个样式,但是不同标签非常有用。样式覆盖这里所说的样式覆盖,主要是一些交互上的行为(hover, active)覆盖。其实组件继承也算是覆盖的一种。以往我们的覆盖写法如下:const ListItem = styled.li padding: 0; height: 48px; &amp;.left-item-focus { .left-link { background: ${props =&gt; props.color}; } } &amp;:hover { .left-icon { color: #9e9e9e; // 500 } };而在styled中,我们可以使用styled-components 组件方式对我们的DOM进行引用,从而覆盖样式,如下const Icon = styled.span color: red;;const ListItem = styled.li &amp;:hover ${Icon} { color: green; };这依旧是我们过去的思路来覆盖样式,只是我们把选择器直接使用styled组件引用罢了。拥有这样的接口,就更加让我们无需去思考需要给组件取什么className或者id,从而达到覆盖样式的做法。然而还有我最喜欢的另外一种写法。TIPS:组件的引用必须是styled-components包装后的组件,直接是react的会报错const ListItem = styled.li``;const Icon = styled.span color: red; ${ListItem}:hover &amp; { // &amp; 代表icon组件 color: green; };这段代码实现的是一样的功能,只是我们思路转换了一下。可以发现这样的代码更加没有侵入性。更加符合开放封闭原则,当我们不需要这个Icon组件时,直接把这个Icon删除即可,我们不用去父组件里寻找与该组件有关的样式,不容易造成样式污染。突然觉得眼前一亮,有木有!当然这种“子组件引用父级”的功能,还有更加广泛的引用。你可以选择该DOM任何parent,再对自己进行样式的覆盖。如下:const Icon = styled.span color: red; html.ie-8 &amp; { // fuck ie8 color: blue; } body.xxx &amp; { color: green; };当任何父级带有class都会覆盖Icon的样式。这种“子组件引用父级”的功能也是我最喜欢的功能没有之一。在上面可以看见我们大量使用了&作为选择器,而&还有另外的技巧。const Example = styled.li color: red; &amp; { color:blue; } &amp;&amp; { color: green; };大家可以猜猜,这最终会渲染成什么?<li class=‘sc-gzVnrw fmpfVE’></li>最终会编译成如下class,但是我们的一个&就代表一个class权重也就是说我们最后会渲染原谅色,原因是li被作用于了.fmpfVE.fmpfVE样式表。这个功能非常有用,比如在你使用第三方组件想要覆盖它的样式的时候,我们就可以加多个&来提高样式权重,从而覆盖第三方组件的样式Theme关于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.meckodoGithub: https://github.com/MeCKodo ...

September 3, 2018 · 1 min · jiezi