大前端 - react - CSS-IN-JS

1. 为什么会有CSS-IN-JS

CSS-IN-JS是web项目中将css代码捆绑在javascript代码中的解决方案,这种方案旨在解决css的局限性,例如缺乏动态功能,作用域和可移植性。

2. CSS-IN-JS介绍

优点:

  1. 让CSS代码拥有独立的作用域,阻止CSS代码泄露到组件外部,防止样式冲突。
  2. 让组件更具可移植性,实现开箱即用,轻松创建松耦合的应用程序。
  3. 让组件更具可重用性,只需编写一次即可,可以在任何地方运行.不仅可以在同一-应用程序中重用组件,而且可以在使用相同框架构建的其他应用程序中重用组件。
  4. 让样式具有动态功能,可以将复杂的逻辑应用于样式规则,如果要创建需要动态功能的复杂UI,它是理想的解决方案

缺点:

  1. 为项目增了了额外的复杂性
  2. 自动生成的选择器大大降低了代码的可读性

优点 > 缺点

3. Emotion 库

以react为例:
Emotion是一个旨在使用jsvascript编写css样式的库
npm install @emotion/core @emotion/styled

  • babel配置以支持css属性的两种方式
    方案1.
    css属性支持
    /** @jsx jsx */: 通知babel,不用再将jsx语法转换成React.createElement方法,而是需要转换为jsx方法
// 必须这样写
/** @jsx jsx */
import { jsx } from '@emotion/core'
function App() {
	return <div css={{width:200, height: 200, background: 'red'}}>app works</div>
}
export default App

方案2.

  1. npm run eject (项目需要加入到git仓库, 可以弹射出项目底层配置)
  2. npm install @emotion/babel-preset-css-prop
  3. 在package.json文件中找到babel属性,加入如下内容:
"babel": {
	"presets": [
  "react-app",
  "@emotion/babel-preset-css-prop"
]
}


在这里插入图片描述
4. 这样就可以正常解析了

function App() {
	return <div css={{width:200, height: 200, background: 'red'}}>app works</div>
}
export default App
3.2 css方法的使用方式
  1. string styles
const style = css`
width: 100px;
height: 100px;
background: red;
`
<div css={style}>app workds</div>
  1. Object styles
const style= css({
	width: 200,
	height:200,
	background: 'red'
})
<div css={style}>app workds</div>
3.3 css属性优先级

props对象中的css属性优先级高于组件内部的css属性。
在调用组件时可以在覆盖组件默认样式。

  1. 验证:props对象中的css属性优先级高于组件内部的css属性。
// css.js
import React from 'react'
import {css} from '@emotion/core'

const style = css`
width: 200px;
height: 200x;
background: skyblue
`
function Css(){
	return <div css={style} {...props}>
		css
	</div>
}
export default Css
import Css from './css.js'
const style=css`
background: pink
`
function  App(){
	return <div >
		<Css css = {style}/>	
	</div>
}
export default App
  1. 最后浏览器中是pink色。
3.4 创建样式化组件

Style Components样式化组件
样式化组件:就是用来构建用户界面的,是emotion库提供的另外一种为元素添加样式的方法。

1.创建样式化组件

import styled from '@emotion/styled'

// 1.string styles
// 创建Button组件,首字母必须大写
// 创建button对应的样式化组件
const Button = styled.button`
color: red,
width: 100px;
height:20px;
`

// 2.object styles
// 创建div对应的样式化组件
const Container = styled.div({
width: 100,
background: pink,
margin: '0 auto'
})

// 使用组件

function  App(){
	return <div >
		<Button>我是按钮</Button>
		<Container>我是container组件</Container>
	</div>
}
export default App


3.5 样式化组件默认样式的覆盖方式

根据props属性覆盖样式
1.string styles

const Button = styled.button`
width: 100px;
height:20px;
background: ${props => props.bgColor || 'skyblue'}
`

2.obejct styles

const Container = styled.div(props=> ({
	width: props.w || 1000,
	background: pink,
	margin: '0 auto'
}))

案例:

import styled from '@emotion/styled'

// 1.string styles
// 创建Button组件,首字母必须大写
// 创建button对应的样式化组件
const Button = styled.button`
color: red,
width: 100px;
height:20px;
backgroun: ${props => props.bgColor || 'skyblue' }

`

// 2.object styles
// 创建div对应的样式化组件
const Container = styled.div(props => (
{
	width: props.w || 1000,
	background: pink,
	margin: '0 auto'
}
))

// 使用组件

function  App(){
	return <div >
		<Button bgColor="pink">我是按钮</Button>
		<Container w={1600}>我是container组件</Container>
	</div>
}
export default App
3.6 为任何组件添加样式
const Demo = ({classname}) => <div classname={classname}>demo</div>
// 1.string styles
const Facy = styled(Demo)`
color: red;
`
// 2.obejct styles
const Facy2 = styled(Demo)({
background: 'tomato',
color: 'white'
})

function  App(){
	return <div >
		<Facy/>
		<Facy2/>
	</div>
}
export default App

3.7 通过父组件设置子组件样式

1.string styles

const Child = styled.div`
color: red
`

const Parent = styled.div`
${Child} {
color: green
}
`
  1. object styles
const Child = styled.div({
color: 'red'
})
const Parent = styled.div({
	[Child] :{
	color: 'green'
	}
})

案例

const Child = styled.div`
color: red
`

const Parent = styled.div`
${Child} {
color: green
}
`

function App() {
	return (
	<>
<Parent>
	<Child> parent child </Child>
</Parent>
</>
)
}
3.8 css选选择器 &

嵌套选择器 & , & 表示组件本身

// 这里的 & 表示:div
// 通过 & 可以找到这个元素的子元素,然后再添加一些样式
const Container = styled.div`
color: red;
& > a {
	color: pink
}
`

案例:

const Container = styled.div`
width: 200px;
height: 200px;
background: skyblue;
color: pink;
& :hoveer{
	background: pink;
}
& > span{
color: yellow
}
`
function App() {
	return (
	<>
<Container>
Container
<span>span</span>
</Container>
</>
)
}

3.9 as 属性

as: 要使用组件中的样式,但要更改呈现的元素

const Button = styled.button`
color: red

`
// 把Button组件当作a标签来使用
<Button as="a" href="#"></Button>
3.10样式组合

在组合样式中,后调用的样式优先级高于先调用的样式。

const base = css`
color: yellow
`
const danger = css`
color: red
`
<button css={[base, danger]}>button</button>
// 最终只会有一个样式。取决于调用顺序,后调用的样式优先级高于先调用的样式。
// danger > base
3.11 Global 组件

定义全局样式

import {css, Global} from '@emotion/core'
const styles =css`
body {
margin: 0
}
`
function App() {
	return (
	<>
<Global styles={styles}>
app works
</Global>
</>
)
} 

3.12 创建主题

1.下载主题模块 npm install emotion-theming
2.引入ThemeProvider 组件

import {ThemeProvider} from ' emotion-theming'
  1. 将ThemeProvider放置在视图最外层
function App(){
	return (
	<>
		<ThemeProvider></ThemeProvider>
	</>
	)
}
  1. 添加主题内容
const theme = {
	colors: {primary: 'hotpink'}
	
}
<ThemeProvider theme={theme}></ThemeProvider>
  1. 获取主题内容(方案1)
const getPrimaryColor = props => css`
color: ${props.colors.primary}
`

<div css={getPrimaryColor}></div>
  1. 获取主题内容(方案2)
import {useTheme} from 'emotion-theming'
function Demo() {
	const theme = useTheme()
}

案例:
index.js

import {ThemeProvider} from ' emotion-theming'
import ReactDom from 'react-dom'

const theme = {
colors: {
	primary: 'tomato'
}
}
 ReactDom.render(
<ThemeProvider theme={theme}>
<App/> 
</ThemeProvider>
, document.getElementById('root')
)

App.js

import {css} from '@emotion/core'
//  方案2:获取和主题内容
import {useTheme} from 'emotion-theming'
//  方案1:获取和主题内容
const primaryColor = props => css`
color: ${props.colors.primary}
`
function App() {
	console.log(useTheme)
	return (
	<div css={primaryColor}></div>
	)
}
export default App
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值