Css in Js 一次实践

栏目: CSS · 发布时间: 5年前

内容简介:最近需要做一个表格组件,组件需求:最终采用grid实现需求。实现的时候遇到一个问题,如果css和js分开写,css只能是定值,没有灵活性。所以考虑采用在github上找了一下关于这方面的组件,发现styled components 非常不错,简单易上手,

最近需要做一个表格组件,组件需求:

  1. 指定行、列
  2. 可以跨行、跨列
  3. 行和行之间有分割线

最终采用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。

Css in Js 一次实践

可以看到,它的实现方式并不是传统的以对象的形式写样式,而是将需要添加样式的元素加到styled对象上,然后跟一个(``)反引号标签,在里面以正常的css格式写样式。然后返回一个组件,把组件替换原来的div即可。

实现效果:

Css in Js 一次实践

html代码:

Css in Js 一次实践

css代码:

Css in Js 一次实践

刚才我们添加样式的元素是html元素,那么给组件添加样式可以么?实践一下:

const H1 = ({ className }) => <h3 className={className}>我是App</h3>;
const HH = styled.H1`
  font-size: 30px;
  color: red;
`;
复制代码

运行,报错:

Css in Js 一次实践

咋回事?原来styled不支持以 . 符号的形式为组件添加样式,需要以参数形式传递,修改上面代码

const HH = styled(H1)`
  font-size: 30px;
  color: red;
`;
复制代码

H1 组件以参数形式传递给styled,就可以了。

Css in Js 一次实践

想给元素添加伪元素样式,子元素样式可以么?没问题, 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,也非常容易实现。想尝试的小伙伴现在就可以码一遍。不过本章遗留了很多问题:

  1. styled.div & styled(div) 有什么区别
  2. 模版字符串中的样式是怎么解析的?为什么可以嵌套?
  3. 为什么会返回一个组件?

下一章,我会根据 styled componnets 源码解答上述问题。

最后,祝生活愉快。


以上所述就是小编给大家介绍的《Css in Js 一次实践》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

微创新

微创新

德鲁•博迪、雅各布•戈登堡 / 钟莉婷 / 中信出版社 / 2014-4-5 / 42.00

好产品不一定要颠覆,微小改进就能让用户尖叫! 引爆创新领域的全新方法论 互联网时代行之有效的5大创新策略 创业者、产品经理必读的创新行动指南 《怪诞行为学》作者 丹•艾瑞里 《影响力》作者 罗伯特•西奥迪尼 全球50位最具影响力的商业思想家之一丹尼尔•平克 周鸿祎、黎万强、罗振宇、牛文文、张鹏 联袂重磅推荐 为什么iPod可以在众多mp3产品中......一起来看看 《微创新》 这本书的介绍吧!

MD5 加密
MD5 加密

MD5 加密工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器