19 React学习笔记.React中的样式

组件化天下的CSS

组件化开发中合适的CSS应该符合以下条件:

  • 可以编写局部css:css具备自己的局部作用域,不会随意污染其他组件内的原生;
  • 可以编写动态的css:可以获取当前组件的一些状态,根据状态的变化生成不同的css样式;
  • 支持所有的css特性:伪类,动画,媒体查询等;
  • 编写简洁方便,符合一贯的css风格;

一. 内联样式

官方推荐的一种写法:

  • style接受一个小驼峰命名属性的JS对象,而不是CSS字符串。
  • 并且可以引用state中的状态来设置相关的样式。

优点:

  1. 内联样式之间不会有冲突;
  2. 可以动态获取state中的状态。

缺点:

  1. 写法上使用驼峰标识(和原来css有差异);
  2. 某些样式没有提示;
  3. 大量的样式,代码混乱;
  4. 某些样式无法编写(比如:伪类/伪元素)。
  • 所以官方仍热希望内联样式和普通的css来结合编写。
export default class app extends PureComponent {
  render() {
    const pStyle = {
      color: "orange",
      textDecoration: "underline",
    }
    
    return (
      <div>
        <h2 style={{fontSize: "50px", color:"red"}}>我是标题</h2>
        <p style={pStyle}>我是一段文字描述</p>
      </div>
    )
  }
}

二. 普通样式

  • 单独文件引入。
  • 直接子代选择器 > 用来选择。
    缺点:样式之前会相互层叠掉。

三. css modules

不是React特有解决方案,所有使用了类似webpack配置的环境下都可以使用的。

  • 配置需要我们自己来修改,比如webpack.config.js中modules: true等。
    React脚手架已经内置了css modules的配置:
  • .css/.less/.scss等样式文件都修改成.module.css/.module.less/.module.scss等;
  • 之后就可以引用并使用了。
  • .module.css文件使用时,会动态生成一个name,防止重叠。
import React, { PureComponent } from 'react'
// import './style.module.css'

import style from './style.module.css'


export default class Profile extends PureComponent {
  render() {
    return (
      <div className="profile">
        <h2 className={style.title}>我是Profile的标题</h2>
        <ul className={style.setting}>
          <li>设置列表1</li>
          <li>设置列表2</li>
          <li>设置列表3</li>
        </ul>
      </div>
    )
  }
}

缺陷:

css module确实解决了局部作用域的问题,但仍有缺陷。

  • 引用的类名,不能使用连接符;
  • 所有className都必须使用{style.className}的形式来编写;
  • 不方便动态来修改某些样式,依然需要使用内联样式的方式
  • 看情况选择,相对受欢迎。

四. CSS in JS

官方文档也有相关内容:

  • 一种模式,其中CSS由JS生成而不是在外部文件中定义;
  • 不是React的一部分,由第三方库提供;
    传统开发中,通常会将HTML,CSS,JS进行分离:
  • 但React思想认为JS本身和UI是无法分离的,所以有了JSX语法;
  • 样式也是UI的一部分;
    事实上CSS-in-JS模式就是一种将样式CSS也写到JS中的方式,并可以方便地使用JS中的状态;
  • 某种程度React:All in JS。
  • 比较适用,但这种方式也有很多批评

  • CSS-in-JS通过JS来为CSS赋予一些能力,包括类似于CSS预处理器一样的样式嵌套,函数定义,逻辑复用,动态修改状态等等;
  • CSS处理器中,获取动态状态不好处理;
  • 所以CSS-in-JS是React编写css最为受欢迎的一种解决方案。
    流行的css-in-js库
  • styled-components
  • emotion
  • glamorous

语法补充:标签模板字符串

可以通过模板字符串的方式对一个函数进行调用。

    function test(...args) {
      console.log(args);
    }
    // 普通方式
    test("aaa","bbb","ccc")

    // 模板字符串调用函数
    test`aaaa`
image.png
  • 模板字符串将传进来的东西,当作参数,传入函数中。
  • 将传入的东西默认放到一个数组中
    test`my name is ${name}, age is ${age}`
image.png
  • 先把传进的所有东西放入数组中;
  • 把数组中东西切割成一个个元素;
  • 插值${}语法取到的放在该数组里,并分割模板字符串;
  • 框架用类似正则表达式对模板字符串解析;
    // 插值动态赋值
    test`
      font-size: 15px;
      color: ${props => props.color};
    `

五. styled-components使用

import React, { PureComponent } from 'react'
import styled from 'styled-components';

const HomeWrapper = styled.div`
  font-size: 50px;
  color: red;
`

export default class Home extends PureComponent {
  render() {
    return (
      <HomeWrapper>
        <h2>我是home的标题</h2>
        <div>
          <span>轮播图</span>
        </div>
      </HomeWrapper>
    )
  }
}
image.png
  • 支持伪类,伪元素
import React, { PureComponent } from 'react'
import styled from 'styled-components';
const HomeWrapper = styled.div`
  font-size: 50px;
  color: red;
  .banner {
    background-color:blue;
    span {
      color: #fff;
      &.active {
        color: #f00;
      }
      &:hover{
        color:green;
      }
      &::after{
        content: "aaa"
      }
    }
  }
`
const TitleWrapper = styled.h2`
  text-decoration: underline;
  font-size
`

export default class Home extends PureComponent {
  render() {
    return (
      <HomeWrapper>
        <TitleWrapper>我是home的标题</TitleWrapper>
        <div className="banner">
          <span className="active">轮播图1</span>
          <span className="active">轮播图2</span>
          <span className="active">轮播图3</span>
          <span className="active">轮播图4</span>
        </div>
      </HomeWrapper>
    )
  }
}
  • 以下真实开发中应该把css提到单独文件中。
import React, { PureComponent } from 'react'

import {
  HomeWrapper,
  TitleWrapper
} from "./style"

export default class Home extends PureComponent {
  render() {
    return (
      <HomeWrapper>
        <TitleWrapper>我是home的标题</TitleWrapper>
        <div className="banner">
          <span className="active">轮播图1</span>
          <span className="active">轮播图2</span>
          <span className="active">轮播图3</span>
          <span className="active">轮播图4</span>
        </div>
      </HomeWrapper>
    )
  }
}

styled-components特点:

  1. props穿透,可以添加属性
        // 第一种写法
        <HYInput type="password" />
        
        // 第二种写法,更加强大,可以定义其他属性
const HYInput = styled.input.attrs({
  placeholder: "coderwwq",
  bColor: "red",
})`
  background-color: lightblue;
  border-color: ${props => props.bColor};
`

完整代码

import React, { PureComponent } from 'react'
// import './style.module.css'
import styled from 'styled-components'

/**
 * 特点:
 * 1. props穿透
 * 2. attrs的使用
 * 3. 传入state作为props的属性
*  4. 继承
*  5. 主题设置
 */

const HYInput = styled.input.attrs({
  placeholder: "coderwwq",
  bColor: "red",
})`
  background-color: lightblue;
  border-color: ${props => props.bColor};
  color: ${props => props.color}
`

export default class Profile extends PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      color: "purple",
    }
  }
  render() {
    return (
      <div>
        <input type="password"/>
        <HYInput type="password" color={this.state.color}/>
        <h2>我是Profile的标题</h2>
        <ul>
          <li>设置列表1</li>
          <li>设置列表2</li>
          <li>设置列表3</li>
        </ul>
      </div>
    )
  }
}

主题可以提供共享样式。

// 主题设置 + 继承,代码

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,911评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,014评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 142,129评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,283评论 1 264
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,159评论 4 357
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,161评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,565评论 3 382
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,251评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,531评论 1 292
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,619评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,383评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,255评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,624评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,916评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,199评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,553评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,756评论 2 335