Css in Js 一次實踐

最近須要作一個表格組件,組件需求:css

  1. 指定行、列
  2. 能夠跨行、跨列
  3. 行和行之間有分割線

最終採用grid實現需求。實現的時候遇到一個問題,若是css和js分開寫,css只能是定值,沒有靈活性。因此考慮採用css in js的形式。關於css in js相關的概念介紹能夠參考阮一峯老師的文章:css in js 介紹html

在github上找了一下關於這方面的組件,發現styled components 很是不錯,簡單易上手,git

npm下載:`npm i styled-components -S`
複製代碼

注意: React < 16 須要下載3.x.x版本的github

根據文檔先寫一個簡單的demo。npm

代碼

能夠看到,它的實現方式並非傳統的以對象的形式寫樣式,而是將須要添加樣式的元素加到styled對象上,而後跟一個(``)反引號標籤,在裏面以正常的css格式寫樣式。而後返回一個組件,把組件替換原來的div便可。bash

實現效果:ui

2.png

html代碼:this

3.png

css代碼:spa

4.png

剛纔咱們添加樣式的元素是html元素,那麼給組件添加樣式能夠麼?實踐一下:3d

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,也很是容易實現。想嘗試的小夥伴如今就能夠碼一遍。不過本章遺留了不少問題:

  1. styled.div & styled(div) 有什麼區別
  2. 模版字符串中的樣式是怎麼解析的?爲何能夠嵌套?
  3. 爲何會返回一個組件?

下一章,我會根據styled componnets源碼解答上述問題。

最後,祝生活愉快。

相關文章
相關標籤/搜索