【青训营】- 关于我不知道的 CSSinJS

1,253 阅读4分钟

这是我参与8月更文挑战的第1天,活动详情查看:8月更文挑战

一、前言

我的青训营系列文章只是用来知识归纳笔记技术分享,而不是教学模板,有问题欢迎大家指出。

本人一个小小带专,自上次更新文章后,就一直在准备着关于升学的问题,所以好久没有看代码和技术帖了,差点一度忘了啥是前端。但是!机缘巧合下,我发现了字节安排的前端青训营活动,便抱着试一试的心理去报名了,然后我就进了(狗头)。青训营的课程十分有趣,字节的技术人员们过来上的课,也有给我们布置作业。在这次半学习半回顾的过程中。做一些以前的技术总结和新学到的东西(顺便蹭蹭8月更文(狗头))。

二、正文

在青训营中,要做个东西出来做展示,而在我们组的技术选型中,因为大家的技术栈各有各的不同,所有在选择样式框架时,选择了CSSinJS框架(好家伙就我一个不会)。

1. 什么是 CSSinJS

字面意思看,其实就是JS 来写 CSS,但是为什么得搞懂没什么呢?
按我理解的意思时,CSSinJS 是专门为了 React 写,其原因是:

  1. Reacthtml 的融合很棒(JSX)但是对 CSS的融合几乎没有(很差)
  2. React中写 CSS经常出现 样式污染难以复用冗余代码等等问题 对于这一现象,导致许多民间大佬起义,为 React封装了一系列的第三方库用于加强 css
    其中一只黑马的野马,便是 styled-components.

2.styled-components 介绍

image.png

我认为 styled-components 受欢迎的几个点:

  • css 就能写,减少学习成本
  • JSCSS,如虎添翼(变量,函数的方法)
  • 把样式融入到组件中,避免了样式污染,按需加载等问题

(1) 下载

# with npm
npm install --save styled-components

# with yarn
yarn add styled-components

官方建议:

强烈建议(但不是必需)也使用Babel 插件。它提供了许多好处,比如更清晰的类名、服务器端渲染兼容性、更小的包等等。

(2) 使用

在需要使用的组件文件里引入即可:

import styled from "styled-components";

看了看文档,粗糙的用了起来

“样式组件”

import styled from "styled-components";

// 定义样式变量
const applered = "#e74c3c";

// 样式组件创建
// const 样式组件名 = styled.创建的元素 ` // 样式内容  `(模板字符串)
export const C1Button = styled.button `
    padding: 12px 24px;
    border: 1px solid ${applered};
    background: #FFFFFF;
    border-radius: 5px;
    color: ${applered};
    outline: none;
    font-size: 14px;
`;

export default class Demo extends Component{
    render(){
        return (
            <div>
                // 使用样式组件
                <C1Button>Hello world</C1Button>
            </div>
        )
    }
}

得到个红彤彤的 button
image.png

想要给 样式组件的元素添加一些属性,需要使用 attr方法进行:

import styled from "styled-components";

// 使用 attr方法给 input标签添加属性
export const NavSearch = styled.input.attrs({
    placeholder: 'search',
    type: 'text',
}) `
    width: 160px;
    height: 38px;
    margin-top: 9px;
    padding: 0 40px 0 20px;
    box-sizing: border-box;
    background-color: #eee;
    outline: none;
    border: none;
    border-radius: 19px;
    color: #666;
    ${// 定义伪类或者伪元素可以使用类似 sass 或 less 的方法 }
    &::placeholder {
        color: #999;
    }
    &.focused {
        width: 240px;
    }

得到一个灰色的输入框:
image.png

全局样式

想要在 styleld-components中设置全局样式,需要而外导入 createGlobalStyle

import styled, {createGlobalStyle} from "styled-components";

// 全局样式
export const globleStyle = createGlobalStyle `
    *{margin: 0;padding: 0}
`;

export default class Demo extends Component{
    render(){
        return (
            <div>
                // 放在组件树的顶部,在渲染时会自动注入全局样式
                <globleStyle></globleStyle>
            </div>
        )
    }
}

但是这玩意有点鸡肋,完全可以用 App.css所代替。

图片导入

对于有的组件需要导入图片的,我们可以将图片通过 import导入后以变量的形式加入样式组件里。如:

import styled from "styled-components";
// 导入图片
import logo from '../logo.svg';

// 创建 img标签样式组件
export const LogoImg = styled.img.attrs({
    src: logo,      // 导入图片
    alt: "no_img",
}) `
    width: 200px;
    border: 1px solid blue;
    border-radius: 5px;
    box-shadow: 5px 5px 5px rgba(0,0,0,.3);
`;

export default class Demo extends Component{
    render(){
        return (
            <div>
                <LogoImg></LogoImg>
            </div>
        )
    }
}

得到一个好看的 React 的logo:

image.png

样式组件继承

当组件多起来后,要写的样式就多了起来,那么按这么写下去就要费很大的功夫去写了。styled-components 提供了样式组件的继承能力。子标签与父标签为同一个标签,且有着相同的样式,但子标签可以自行进行覆盖或添加。

import styled from "styled-components";

// 创建一个父级 div样式组件
export const parentDiv = styled.div `                  
    padding: 12px;
    border-radius: 5px;
    color: #4c4c4c;
    background: #e74c3c;
`;


// 创建一个子级 div样式组件并继承于 parentDiv
// const 子样式组件 = styled(父级样式组件) ``;
export const childDiv = styled(parentDiv) `
    color: green;
    background: #f1c40f;
`;

export default class Demo extends Component{
    render(){
        return (
            <div>
                <parentDiv>
                    <p>This is a text on parent div.</p>
                    <childDiv>
                        <p>This is a text on child div.</p>
                    </childDiv>
                </parentDiv>
            </div>
        )
    }
}

子级的 div在保留了父级的 border-radiuspadding的同时,覆盖了colorbackground

image.png

动画

在原生 CSS 中,动画通过 @keyframes定义,而 styled-components中提供了 keyframes功能用于创建动画。

// 导入
import styled ,{keyframes} from "styled-components";

// 创建一个动画
const rotate = keyframes`
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
`;

// 创建一个div样式组件
export const Windmill = styled.div `
    display: inline-block;
    ${ // 将动画添加到组件上 }
    animation: ${rotate} 2s linear infinite;
    padding: 2rem 1rem;
    font-size: 1.2rem;
`

export default class Demo extends Component{
    render(){
        return (
            <div>
                <Windmill>&lt; 💅 &gt;</Windmill>
            </div>
        )
    }
}

得到了一个可爱的旋转雪糕:

动画.gif

props 传参

这个我是真没想到,styled-components支持获取 props中的值,通过函数获得 props,通过三元运算符或者获取其值,可以做出一些不同的效果:

// 导入
import styled from "styled-components";

// props 取值
export const Button = styled.button<any> `
    padding: 12px 24px;
    border-radius: 5px;
    ${ // 别学我,这样写又累又没效率 }
    border: 1px solid ${(props : any) => props.primary ? "blue" : props.danger ? "red" :  props.warning ? "orange" : props.info ? "black" : props.success ? "green" : "blue"};
    background: ${(props : any) => props.fill ? props.primary ? "blue" : props.danger ? "red" :  props.warning ? "orange" : props.info ? "black" : props.success ? "green" : "#c0c0c0" : "white"};
    color: ${(props : any) => props.fill ? "white" : props.primary ? "blue" : props.danger ? "red" :  props.warning ? "orange" : props.info ? "black" : props.success ? "green" : "blue"};
    outline: none;
    font-size: 14px;
    margin: 6px;
    cursor: pointer;
    transition: all .2s ease-in-out;
    &:hover{
        color: ${(props : any) => props.fill ? props.primary ? "blue" : props.danger ? "red" :  props.warning ? "orange" : props.info ? "black" : props.success ? "green" : "#c0c0c0" : "white"};
        background: ${(props : any) => props.fill ? "white" : props.primary ? "blue" : props.danger ? "red" :  props.warning ? "orange" : props.info ? "black" : props.success ? "green" : "blue"};
    }
    &::after{
        content:"";
    }
`;

export default class Demo extends Component{
    render(){
        return (
            <div>
                <Windmill>&lt; 💅 &gt;</Windmill>
            </div>
        )
    }
}

得到各式各样的按钮:

动画2.gif

总结

styled-components 对于Reactcss 来说,不失为一种好选择,但也不是最优解。
说说我认为的 styled-components 的缺点:

  • 每种样式的标签绑定一种样式(即使你继承做的很好),需要做出许多的样式组件,不易于查看。
  • 对于想做特效或动画、样式变化的情况不是很友好

得出结论:我还是喜欢 sass

最后

有什么问题希望大家可以指明我好及时更正。
我的青训营的文章是作为个人学习笔记的。在开学前在冲刺一下下。

新人上路,还请多多包含。
我是MoonLight,一个初出茅庐的小前端。