前置

在 react 中解决组件样式冲突的方案中,如果您喜欢将 css 与 js 分离,可能更习惯于 CSS-Modules;如果习惯了 Vue.js 那样的单文件组件,可能习惯于使用 styled-components 来解决这个问题。使用 CSS-Modules 从老项目迁移过来可能更容易。

安装

npm i styled-components

基本用法

import React from 'react'
import styled from 'styled-components'
import { render } from 'react-dom'
import './index.css' const items = [
{
title: 'title1',
type: 'primary',
desc: 'Lorem ipsum dolor sit amet consectetur '
},
{
title: 'title2',
type: 'other',
desc: 'Lorem ipsum dolor sit amet consectetur ',
},
] function App() {
return (
<div>
{items.map(renderItem)}
</div>
)
} function renderItem(item) {
return (
<Wrap>
<h2>{item.title}</h2>
<p>{item.desc}</p>
</Wrap>
)
} const Wrap = styled.div`
margin: 10px auto 10px;
padding: 10px;
width: 90%;
border-radius: 5px;
background: #eee
` render(<App />, document.getElementById('app'))

实际渲染结果:



我们需要在 JavaScript 模板字符串内部书写 css 样式,为了得到 css 语法高亮,可以使用 vscode 扩展。

嵌套

const Wrap = styled.div`
margin: 10px auto;
padding: 10px;
width: 90%;
border-radius: 5px;
background: #eee; + h2 {
+ color: red
+ }
`

props

function renderItem(item) {
return (
+ <Wrap type={item.type} >
<h2>{item.title}</h2>
<p>{item.desc}</p>
</Wrap>
)
} const Wrap = styled.div`
margin: 10px auto;
padding: 10px;
width: 90%;
border-radius: 5px;
+ background: ${props => props.type === 'primary' ? '#202234' : '#eee'};
`

在模板括号中可使用任意 JavaScript 表达式,这里使用箭头函数,通过 props 接收参数。

继承

使用继承实现上文功能:

import React from 'react'
import styled from 'styled-components'
import { render } from 'react-dom'
import './index.css' const items = [...] function App() {
return (...)
} function renderItem(item) {
+ const Container = item.type === 'primary' ? primaryContainer : OrdinaryContainer
return (
+ <Container>
<h2>{item.title}</h2>
<p>{item.desc}</p>
</Container>
)
} const Wrap = styled.div`
margin: 10px auto 10px;
padding: 10px;
width: 90%;
border-radius: 5px;
- background: ${props => props.type === 'primary' ? '#202234' : '#eee'};
` + const OrdinaryContainer = styled(Wrap)`
+ background: #eee;
+ ` + const primaryContainer = styled(Wrap)`
+ background: #202234;
+ ` render(<App />, document.getElementById('app'))

我们得到同样的效果:

继承的语法

// 如上所示,您应该这样写来实现继承
const OrdinaryContainer = styled(Wrap)``
// 现在已经不支持extend关键字
const OrdinaryContainer = Wrap.extend``

下面给它们共同继承的 Wrap 添加一个border:

const Wrap = styled.div`
margin: 10px auto 10px;
padding: 10px;
width: 90%;
border-radius: 5px;
+ border: 2px solid red;
`

将影响所有继承过 Wrap 的样式变量:

attrs

封装一个文本输入框组件 src/components/Input.jsx

import styled from "styled-components";

const Input = styled.input.attrs({
type: 'text',
padding: props => props.size || "0.5em",
margin: props => props.size || "0.5em"
})`
border: 2px solid #eee;
color: #555;
border-radius: 4px;
margin: ${props=>props.margin};
padding: ${props=>props.padding};
` export default Input

使用

// ..
import Input from './components/Input' function App() {
return (
<div>
<Input></Input>
<Input size="2em"></Input>
</div>
)
} render(<App />, document.getElementById('app'))

createGlobalStyle

在 V4 版本已经将 injectGlobal 移除,使用 createGlobalStyle 代替它设置全局样式,

import React from 'react'
import { render } from 'react-dom'
import styled, {createGlobalStyle} from 'styled-components' // ... function App() {
return (
<div>
<GlobalStyle></GlobalStyle>
{items.map(renderItem)}
</div>
)
} function renderItem(item) {
const Container = item.type === 'primary' ? primaryContainer : OrdinaryContainer
return (
<Container>
<h2>{item.title}</h2>
<p>{item.desc}</p>
</Container>
)
} const GlobalStyle = createGlobalStyle`
*{
margin: 0;
padding: 0;
}
body {
min-height: 100%;
background: #ffb3cc;
}
`
// ... render(<App />, document.getElementById('app'))

ThemeProvider

通过上下文 API 将主题注入组件树中位于其下方任何位置的所有样式组件中。

import React from 'react'
import { render } from 'react-dom'
import styled, {createGlobalStyle, ThemeProvider} from 'styled-components'
import Input from './components/Input' const items = [...] function App() {
return (
<div>
<GlobalStyle></GlobalStyle>
{items.map(renderItem)}
<Input></Input>
<Input size="2em"></Input>
</div>
)
} function renderItem(item) {
const Container = item.type === 'primary' ? primaryContainer : OrdinaryContainer
return (
<Container>
<h2>{item.title}</h2>
<p>{item.desc}</p>
</Container>
)
} // ... const primaryContainer = styled(Wrap)`
background: ${props=>props.theme.primary};
` const theme = {
primary: '#202234'
} render(<ThemeProvider theme={theme}><App /></ThemeProvider>, document.getElementById('app'))

我们需要先导入 ThemeProvider,然后用标签将 <App /> 包裹,需要注意的是必须为 ThemeProvider 标签提供一个 theme 属性,接下来在所有子组件中都可以通过 props.theme.xxx 获取 theme 下的属性。我们将 Input 组件的背景色同样改为 theme 下的 primary

import styled from "styled-components";

const Input = styled.input.attrs({
// ...
})`
// ...
background: ${props=>props.theme.primary};
` export default Input

keyframes

使用 styled-components 时,无法直接在模板字符串中创建 keyframes,需要先导入 styled-components 下的 keframes 对象来创建它。下面看一个简单的实例:

import React from 'react'
import styled, { keyframes } from 'styled-components'
import { render } from 'react-dom' const items = [...] function App() {
return (
<div>
{items.map(renderItem)}
</div>
)
} function renderItem(item) {
const Container = item.type === 'primary' ? primaryContainer : OrdinaryContainer
return (
<Container>
<h2>{item.title}</h2>
<p>{item.desc}</p>
</Container>
)
} // ... const fadeIn = keyframes`
0% {
opacity: 0;
}
100% {
opacity: 1;
}
` const Wrap = styled.div`
// ...
animation: 1.5s ${fadeIn} ease-out;
`
// .. render(<App />, document.getElementById('app'))

到我重新刷新页面,就能看见下面的效果:

react 样式冲突解决方案 styled-components的更多相关文章

  1. styled components草根中文版文档

    1.styled components官网网址 https://www.styled-components.com/docs   以组件的形式来写样式. 1.1安装 yarn add styled-c ...

  2. react className 有多个值时的处理 / react 样式使用 百分比(%) 报错

    1.react className 有多个值时的处理 <fieldset className={`${styles.formFieldset} ${styles.formItem}`}> ...

  3. 百度地图api的覆盖物样式与bootstrap样式冲突解决办法

    使用百度地图api 和 bootstrap ,发现标注样式出现了问题 label左侧 宽度变得非常窄 正常情况下应该是下面这样的: 原因是boostrap样式和百度地图样式冲突了. 解决办法: .ba ...

  4. Atitit 类库冲突解决方案  httpclient-4.5.2.jar

    Atitit 类库冲突解决方案  httpclient-4.5.2.jar 错误提示如下1 版本如下(client and selenium)2 解决流程2 挂载源码 (SSLConnectionSo ...

  5. SVN代码提交冲突解决方案

    SVN代码提交冲突解决方案 1.若你的代码被其他人修改并提交过了,期间你自己也修改过该文件,UPDATE的时候自己代码被覆盖. 右键——>显示日志 查看该文件的更新记录 找到需恢复的版本 右键— ...

  6. SharePoint 2010 中使用Ztree和EasyUI样式冲突问题

    <style type="text/css"> /*解决ztree和SharePoint样式冲突问题*/ .ztree li a { display: inline-b ...

  7. Git冲突解决方案

    Git冲突解决方案 1.  在代码提交时,先更新,若有冲突.先解决冲突.若提交之后在review时才发现无法合并代码时有冲突,需要abandon此次提交的代码. 2.  解决冲突的基本做法,保存本地代 ...

  8. vue2.0 通过v-html指令渲染的富文本无法修改样式的解决方案

    在最近的vue项目中遇到的问题:v-html渲染的富文本,无法在样式表中修改样式: 比如下面的代码,div.descBox里面的p标签的color样式并不是"color: blue" ...

  9. PC端的软件端口和adb 5037端口冲突解决方案

    引用https://www.aliyun.com/jiaocheng/32552.html 阿里云 >  教程中心   >  android教程 >  PC端的软件端口和adb 50 ...

随机推荐

  1. 老司机带你玩转面试(1):缓存中间件 Redis 基础知识以及数据持久化

    引言 今天周末,我在家坐着掐指一算,马上又要到一年一度的金九银十招聘季了,国内今年上半年受到 YQ 冲击,金三银四泡汤了,这就直接导致很多今年毕业的同学会和明年毕业的同学一起参加今年下半年的秋招,这个 ...

  2. 老司机带你玩转面试(2):Redis 过期策略以及缓存雪崩、击穿、穿透

    前文回顾 建议前一篇文章没看过的同学先看下前面的文章: 「老司机带你玩转面试(1):缓存中间件 Redis 基础知识以及数据持久化」 过期策略 Redis 的过期策略都有哪些? 在聊这个问题之前,一定 ...

  3. Apache Kylin v3.1.0 重点功能推介

    Apache Kylin v3.1.0 已于上周正式发布,其中包含了许多值得一试的新功能,本文选择了 Presto 查询下压引擎.Flink 构建引擎.Kylin on Kubernetes 解决方案 ...

  4. TCP 和 UDP,哪个更胜一筹

    作为 TCP/IP 中两个最具有代表性的传输层协议,TCP 和 UDP 经常被拿出来相互比较.这些协议具体有什么区别,又是什么作用呢? 在 IT 圈混迹多年的小伙伴们,对 TCP 和 UDP 肯定再熟 ...

  5. Python实现性能自动化测试竟然如此简单【颠覆你的三观】

    一.思考 1.什么是性能自动化测试?   性能系统负载能力 超负荷运行下的稳定性 系统瓶颈 自动化测试使用程序代替手工 提升测试效率 性能自动化使用代码模拟大批量用户 让用户并发请求 多页面多用户并发 ...

  6. Ethical Hacking - Web Penetration Testing(7)

    VULNS MITIGATION 1. File Upload Vulns - Only allow safe files to be updated. 2. Code Execution Vulns ...

  7. 设计模式:observer模式

    目标:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新 例子: class Observer //观察者 { public: virtual vo ...

  8. [jvm] -- 引用篇

    四种引用及其应用场景 强引用 强引用是平常中使用最多的引用,强引用在程序内存不足(OOM)的时候也不会被回收. 使用场景:啥时候都在使用 软引用 软引用在程序内存不足时,会被回收. 使用场景:创建缓存 ...

  9. select、poll和epoll之间的区别

    在深入理解select.poll和epoll之间的区别之前,首先要了解什么是IO多路复用模型. IO多路复用 简单来说,IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备就绪,它就通知该进 ...

  10. Java的常用类——Object类、String类

    Java的JDK中提供给我们很多封装好的类就是Java API,可以直接调用. Java 的API(API: Application(应用) Programming(程序) Interface(接口) ...