React中编写CSS实例详解

目录
  • 正文
  • 内联样式
  • 普通的CSS
  • css modules
  • css in js
    • 样式组件
    • 引入外部变量
    • 默认值
    • 引入全局样式
    • provider
    • 样式继承
  • 动态添加class

正文

目前,前端最流行的开发方式是组件化,而CSS的设计本身就不是为组件化而生的,所以在目前组件化的框架中都在需要一种合适的CSS解决方案

在组件化开发环境下的CSS,应该满足如下需求:

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

Vue在CSS上虽然不能称之为完美,但是已经足够简洁、自然、方便了,至少统一的样式风格不会出现多个开发人员、多个项目 采用不一样的样式风格

相比而言,React官方并没有给出在React中统一的样式风格

由此,从普通的css,到css modules,再到css in js,有几十种不同的解决方案,上百个不同的库

大家一致在寻找最好的或者说最适合自己的CSS方案,但是到目前为止也没有统一的方案

内联样式

内联样式是官方推荐的一种css样式的写法:

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

优点

  • 内联样式, 样式之间不会有冲突
  • 可以动态获取当前state中的状态

缺点

  • 写法上都需要使用驼峰标识
  • 某些样式没有提示
  • 大量的样式, 代码混乱
  • 某些样式无法编写(比如伪类/伪元素)

所以官方依然是希望内联合适和普通的css来结合编写

import React, { PureComponent } from 'react'
export class App extends PureComponent {
  constructor(props) {
    super(props)
    this.state = {
      color: 'red'
    }
  }
  render() {
    return (
      <div style={{ colot: this.state.color, backgroundColor: 'skyblue' }}>App</div>
    )
  }
}
export default App

普通的CSS

普通的css我们通常会编写到一个单独的文件,之后再进行引入

这样的编写方式和普通的网页开发中编写方式是一致的

但是使用这种方式编写我们的css有一个致命缺点,即没有自己的样式作用域

默认引入的样式都是全局样式

import React, { PureComponent } from 'react'
import './style.css'
export class App extends PureComponent {
  constructor(props) {
    super(props)
    this.state = {
      color: 'red'
    }
  }
  render() {
    return (
      <div>App</div>
    )
  }
}
export default App

css modules

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

如果在其他项目中使用它,那么我们需要自己来进行配置,比如配置webpack.config.js中的modules: true等

如果使用React脚手架,其内部已经内置了css modules的配置

.css/.less/.scss 等样式文件都需要修改成 .module.css/.module.less/.module.scss 等 之后就可以引用并且进行使用了

import React, { PureComponent } from 'react'
// 引入css modules - 实际会将对应的css文件编译为一个JS对象
// 当我们将一个样式文件的后缀名修改为 .module.css的时候,对应样式文件就变成了css样式模块
import AppStyle from './style.module.css'
export class App extends PureComponent {
  constructor(props) {
    super(props)
    this.state = {
      color: 'red'
    }
  }
  render() {
    return (
      <div>
				{/*
					css modules 会将css文件编译为js对象,所以需要向属性那样使用
					同理 如果使用了一个样式模块中不存在的样式,对应值就是undefined
					实际表现为对应元素样式不生效, 页面并不会报错
				*/}
				<h2 className={AppStyle.title}>title</h2>
				{/*
					对应的样式会被编译w为 style_content__O3F7P
					也就是 [样式文件名]_[样式名]__[hash值]
					从而避免出现样式冲突
				*/}
				<p className={AppStyle.content}>content</p>
			</div>
    )
  }
}
export default App

但是CSS modules依旧存在自己的缺点

  • 引用的类名,不能直接使用连接符(.home-title),需要使用中括号语法,因为连字符在JavaScript中是不识别的
  • 所有的className都必须使用{style.className} 的形式来编写
  • 不方便动态来修改某些样式,依然需要使用内联样式的方式

css in js

“CSS-in-JS” 是指一种模式,其中 CSS 由 JavaScript 生成而不是在外部文件中定义

注意此功能并不是 React 的一部分,而是由第三方库提供

React的思想中认为逻辑本身和UI是无法分离的,所以才会有了JSX的语法

事实上CSS-in-JS的模式就是一种将样式(CSS)也写入到JavaScript中的方式,并且可以方便的使用JavaScript的状态

所以React有被人称之为 All in JS

CSS-in-JS通过JavaScript来为CSS赋予一些能力,包括类似于CSS预处理器一样的样式嵌套、函数定义、逻辑复用、动态修 改状态等等

所以,目前可以说CSS-in-JS是React编写CSS最为受欢迎的一种解决方案

目前最为常用的css-in-js库是 styled-components

npm install styled-components

组件

import React, { PureComponent } from 'react'
// 使用css in js后,对应的样式直接编写在js文件中即可
import AppWrapper from './style.js'
export class App extends PureComponent {
  render() {
    return (
      <AppWrapper>
				<h2 className="title">title</h2>
				<p className="content">content</p>
			</AppWrapper>
    )
  }
}
export default App

样式

import styled from 'styled-components'
// styled.div本质上是一个函数  需要通过标签模板字符串进行调用 并返回一个新的有对应样式的组件
// ps: 默认情况下对应样式是不会高亮的,需要高亮可以安装vscode-styled-components插件
export default styled.div`
	/* 对应样式会被编译为 .jaGVDq */
	/* 即一个唯一的hash值 */
	/* 所以使用styled-components编写对应的样式会存在自己的样式作用域 */
	/* 组件和组件之间的样式是不会冲突的 */
	/*
		但因为编译后的样式类似于 .jaGVDq .content
		所以在实际使用过程中,对于后代选择器仍然可能出现样式冲突的情况
  */
	background-color: #f5f5f5;
	/* .jaGVDq .title */
	.title {
		color: red;
		&:hover {
			background-color: gray;
		}
	}
	/* .jaGVDq .content */
	.content {
		color: skyblue
	}
`

样式组件

import styled from 'styled-components'
export default styled.div`
	background-color: #f5f5f5;
	.content {
		color: skyblue
	}
`
// 如果某一块的样式比较多,可以将对应的样式进行单独抽离
// 形成一个独立的样式组件
export const TitleWrapper = styled.h2`
	color: red;
	&:hover {
		background-color: gray;
	}
`

引入外部变量

import React, { PureComponent } from 'react'
import AppWrapper from './style.js'
export class App extends PureComponent {
	constructor(props) {
		super(props)
		this.state = {
			color: 'skyblue'
		}
	}
  render() {
    return (
			// AppWrapper本质上是一个组件
			// 所以对应的样式直接以props的形式进行传入即可
      <AppWrapper color={ this.state.color }>
				<h2 className="title">title</h2>
				<p className="content">content</p>
			</AppWrapper>
    )
  }
}
export default App
import styled from 'styled-components'
export default styled.div`
	.title {
		/*
			如果直接使用props.color 在js中 会沿着作用域链去查找对应的props
			所以直接使用props 在css in js中是不合适的
			所以在styled-components中引入外部变量的时候,需要传入一个回调函数
			该回调函数的参数为外部传入的props,返回值是所需要设置的对应样式值
		*/
		color: ${ props => props.color };
		&:hover {
			background-color: gray;
		}
	}
	.content {
		color: gray
	}
`

默认值

import styled from 'styled-components'
// 因为styled-components 本质上就是css in js
// 所以我们也可以通过如下方式来使用styled-components
export default styled.div`
	.title {
		// 解构语法
		color: ${ ({ color }) => color };
		&:hover {
		  // 解构的时候 设置对应的默认值
			background-color: ${ ({ bgColor = 'yellow' }) => bgColor };
		}
	}
	.content {
	 	// 空值合并操作符
		color: ${ ({ contentColor }) => contentColor ?? 'orange' }
	}
`

有的时候,我们希望在外部没有传入对应props的时候,可以存在对应的默认值

但是使用上述写法,每使用一次就需要单独设置一次对应的默认值,这必然是十分麻烦的

所以styled-components提供了attrs方法,专门用于设置默认值

import styled from 'styled-components'
// attrs方法会返回对应的含有样式的样式组件
// 所以在这里可以链式调用
// 在attrs中可以传入一个回调函数,用于设置对应的默认值
// 回调函数在被调用的时候会将对应的props传递过来
export default styled.div.attrs(props => ({
	contentColor: props.contentColor ?? 'purple'
}))`
	.title {
		color: ${ props => props.color };
		&:hover {
			background-color: gray;
		}
	}
	.content {
		color: ${ props => props.contentColor }
	}
`

引入全局样式

/style/theme.js --- 全局的主题样式文件

export const primaryColor = '#409eff'
export const warnColor = '#e6a23c'
export const successColor = '#67c23a'

样式组件

import styled from 'styled-components'
import {
	primaryColor,
	successColor
} from '../style/theme'
export default styled.div`
	.title {
		color: ${ successColor };
		&amp;:hover {
			background-color: gray;
		}
	}
	.content {
		color: ${ primaryColor }
	}
`

provider

app.jsx

import ReactDOM from 'react-dom/client'
import App from './App'
import { StrictMode } from 'react'
import { ThemeProvider } from 'styled-components';
ReactDOM.createRoot(document.querySelector('#root')).render(
	<StrictMode>
		{/*
			ThemeProvider 是 styled-components中 导出的 context
			通过theme属性来设置对应的全局变量值
		*/}
		<ThemeProvider theme={{ color: 'skyblue' }}>
			<App />
		</ThemeProvider>
	</StrictMode>
)
import styled from 'styled-components'
export default styled.div`
	.title {
		/* ThemeContext中提供的全局样式值会被传入到 props.theme中 */
		color: ${ props => props.theme.color };
	}
	.content {
		color: red
	}
`

样式继承

const OriginButton = styled.button`
	border-radius: 5px;
`
export const PrimaryButton = styled(OriginButton)`
	color: #fff;
	background-color: #409eff;
`

动态添加class

写法一 --- 使用三元运算符

import React, { PureComponent } from 'react'
export class App extends PureComponent {
	constructor(props) {
		super(props)
		this.state = {
			isActive: true,
			isCurrent: true
		}
	}
	render() {
		const { isActive, isCurrent } = this.state
		return (
			<div>
				<div className={ `${isActive ? 'active' : '' } ${ isCurrent ? 'current' : '' }` }>active</div>
			</div>
		)
	}
}
export default App

写法二 --- 使用join方法

import React, { PureComponent } from 'react'
export class App extends PureComponent {
	constructor(props) {
		super(props)
		this.state = {
			isActive: true,
			isCurrent: true
		}
	}
	render() {
		const { isActive, isCurrent } = this.state
		const activeClass = []
		if (isActive) {
			activeClass.push('active')
		}
		if (isCurrent) {
			activeClass.push('current')
		}
		return (
			<div>
				<div className={ activeClass.join(' ') }>active</div>
			</div>
		)
	}
}
export default App

写法三 --- 使用第三方库 classnames

npm install classnames
classNames('foo', 'bar'); // => 'foo bar'
classNames('foo', { bar: true }); // => 'foo bar'
classNames({ 'foo-bar': true }); // => 'foo-bar'
classNames({ 'foo-bar': false }); // => ''
classNames({ foo: true }, { bar: true }); // => 'foo bar'
classNames({ foo: true, bar: true }); // => 'foo bar'
// classnames 支持多种编写方式 混合使用
classNames('foo', { bar: true, duck: false }, 'baz', { quux: true }); // => 'foo bar baz quux'
// 只要是falsy值的结果 全部都会被忽略
classNames(null, false, 'bar', undefined, 0, 1, { baz: null }, ''); // => 'bar 1'
// classnames 支持 数组写法 和 计算属性名
className={ classnames([{ [activeClass]: isActive }, { current: isCurrent }])

以上就是React中编写CSS实例详解的详细内容,更多关于React编写CSS的资料请关注我们其它相关文章!

(0)

相关推荐

  • React使用emotion写css代码

    简介: emotion是一个JavaScript库,使用emotion可以用写js的方式写css代码.在react中安装emotion后,可以很方便进行css的封装,复用.使用emotion后,浏览器渲染出来的标签是会加上一个css开头的标识.如下:截图中以css-开头的几个标签,就是使用emotion库后渲染出来的. 下面就从安装到使用,介绍下emotion在工程中的应用. emotion的安装: yarn add @emotion/react yarn add @emotion/styled

  • 如何用react优雅的书写CSS

    1.内联样式 优点:这种方式较为简单,一目了然,给标签添加style属性. 缺点: 这种方式可以造成项目结构较为臃肿,造成css命名冲突. import React, { Component } from 'react' import PropTypes from 'prop-types' export default class index extends Component { static propTypes = { title: PropTypes.string } render() {

  • 基于react项目打包css引用路径错误解决方案

    没有去修改create-react-app默认的配置文件 执行npm start 一切正常, 但是 npm run build 之后生成的打包文件只能在根目录访问 这样放在服务器目录就访问不到了 报错为 手动更改index.html的路径之后又报静态资源引入错误 报错 解决方案 解决: 在package.json下面增加"homepage": ".". 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们.

  • react项目引入scss的方法

    首先下载依赖 yarn add sass-loader node-sass 然后在项目路径 node_modules/react-scripts/config/webpack.config.js 打开文件 找到 加入红线内的代码 { test:/\.scss$/, loaders: ['style-loader', 'css-loader', 'sass-loader'] }, 就可以使用scss了 知识点扩展: React pwa的配置 在到webpack配置文件中添加插件 const Wor

  • 详解react的两种动态改变css样式的方法

    第一种:动态添加class,以点击按钮让文字显示隐藏为demo import React, { Component, Fragment } from 'react'; import './style.css'; class Demo extends Component{ constructor(props) { super(props); this.state = { display: true } this.handleshow = this.handleshow.bind(this) thi

  • react使用CSS实现react动画功能示例

    本文实例讲述了react使用CSS实现react动画功能.分享给大家供大家参考,具体如下: react动画: import React, { Component } from 'react'; class Boss extends Component { constructor(props) { super(props); this.state = { isShow:true } this.toTogger=this.toTogger.bind(this) } render() { return

  • React中编写CSS实例详解

    目录 正文 内联样式 普通的CSS css modules css in js 样式组件 引入外部变量 默认值 引入全局样式 provider 样式继承 动态添加class 正文 目前,前端最流行的开发方式是组件化,而CSS的设计本身就不是为组件化而生的,所以在目前组件化的框架中都在需要一种合适的CSS解决方案 在组件化开发环境下的CSS,应该满足如下需求: 可以编写局部css: css具备自己的具备作用域,不会随意污染其他组件内的元素 可以编写动态的css: 可以获取当前组件的一些状态,根据状

  • js中自定义react数据验证组件实例详解

    我们在做前端表单提交时,经常会遇到要对表单中的数据进行校验的问题.如果用户提交的数据不合法,例如格式不正确.非数字类型.超过最大长度.是否必填项.最大值和最小值等等,我们需要在相应的地方给出提示信息.如果用户修正了数据,我们还要将提示信息隐藏起来. 有一些现成的插件可以让你非常方便地实现这一功能,如果你使用的是knockout框架,那么你可以借助于Knockout-Validation这一插件.使用起来很简单,例如我下面的这一段代码: ko.validation.locale('zh-CN');

  • Linux 在Shell脚本中使用函数实例详解

    Linux 在Shell脚本中使用函数实例详解 Shell的函数 Shell程序也支持函数.函数能完成一特定的功能,可以重复调用这个函数. 函数格式如下: 函数名() { 函数体 } 函数调用方式: 函数名 参数列表 实例:编写一函数add求两个数的和,这两个数用位置参数传入,最后输出结果. root@ubuntu:/home/study# vi test3 #!/bin/bash add(){ a=$1; b=$2; z=`expr $a + $b`; echo "The sum is $z&

  • python中time包实例详解

    在python中基础的时间运用,离不开time函数的支持.这些函数为了方便调用集中放在一个地方,叫做time包.有的人会仔细追寻time包的来源,会发现它和C语言有密不可分的关系.下面我们简单介绍time包的概念,然后就包中的一些函数进行列举,并附上对应的使用方法. 1.概念 time包基于C语言的库函数(library functions).Python的解释器通常是用C编写的,Python的一些函数也会直接调用C语言的库函数. 2.time包中的函数 time.clock()返回程序运行的整

  • python+flask编写接口实例详解

    环境:Pycharm :其他环境:安装Anaconda 最近在做一个小型项目练手,涉及到大量的IP和相关数据处理,所以选用了Python来处理数据,但是处理完怎么给前端调用呢,今天这篇就是在Python方便地处理完数据后以接口形式把数据返回给前端. flask就是使用Python编写接口实例的关键库,先配置项目: ①(这一步可以使用Python默认解释器,但是后续安装库可能还需要配置,建议使用Anaconda)首先打开PyCharm,在file->settings->Project->p

  • React中的生命周期详解

    目录 react生命周期 常用的生命周期 不常用的生命周 完整的生命周期图 react生命周期 函数组件无生命周期,生命周期只有类组件才拥有 生命周期函数指在某一时刻组件会自动调用并执行的函数. React每个类组件都包含生命周期方法,以便于在运行过程中特定的阶段执行这些方法. 例如:我们希望在第一次将其呈现到DOM时设置一个计时器Clock.这在React中称为“安装”.我们也想在删除由产生 的DOM时清除该计时器Clock.这在React中称为“卸载”. 一般分为:挂载.更新.卸载 常用的生

  • Angularjs中数据绑定的实例详解

    Angularjs中数据绑定的实例详解 这是一个最简单的angularjs的例子,关于数据绑定的,大家可以执行一下,看看效果 <html ng-app> <head> <title>angularjs-include</title> <script type="text/javascript" src="js/angular/angular.min.js"></script> </head

  • C++ 中构造函数的实例详解

    C++ 中构造函数的实例详解 c++构造函数的知识在各种c++教材上已有介绍,不过初学者往往不太注意观察和总结其中各种构造函数的特点和用法,故在此我根据自己的c++编程经验总结了一下c++中各种构造函数的特点,并附上例子,希望对初学者有所帮助. 1. 构造函数是干什么的 class Counter { public: // 类Counter的构造函数 // 特点:以类名作为函数名,无返回类型 Counter() { m_value = 0; } private: // 数据成员 int m_va

  • JSP Spring配置文件中传值的实例详解

    JSP Spring配置文件中传值的实例详解 通过spring提供方法,在配置文件中取传值 调用get方法  targetObject :指定调用的对象       propertyPath:指定调用那个getter方法 例1: public class Test1 { private String name = "nihao"; public String getName() { return name; } } Xml代码 <bean id="t1" cl

  • java 中匿名内部类的实例详解

    java 中匿名内部类的实例详解 原来的面貌: class TT extends Test{ void show() { System.out.println(s+"~~~哈哈"); System.out.println("超级女声"); } TT tt=new TT(); tt.show(); 只是说我们这里采用的是匿名的形式来处理. 重写了Test的show()方法,在重写好了以后,又调用了重写后的show()方法 实现代码: package cn.com; c

随机推荐