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=>{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: ${()=> { let arr = []; arr.length = col; return arr.fill('1fr').join(' '); }}; grid-template-rows: ${()=> { let arr = []; arr.length = row; return arr.fill('1fr').join(' '); }}; grid-gap: ${rowgap} ${colgap} ; justify-items: ${()=> justify || "center"}; ::before { display: none; } li { width: 100% !important; } ${ child.map(({index, colSpan, rowSpan}) =>` 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=>` 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
源码解答上述问题。
最后,祝生活愉快。
相关推荐
background-color: blue;background-color: yellow;<input type="button" value="变蓝" @click="changeColorT