react 样式冲突解决方案 styled-components
前置
在 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的更多相关文章
- styled components草根中文版文档
1.styled components官网网址 https://www.styled-components.com/docs 以组件的形式来写样式. 1.1安装 yarn add styled-c ...
- react className 有多个值时的处理 / react 样式使用 百分比(%) 报错
1.react className 有多个值时的处理 <fieldset className={`${styles.formFieldset} ${styles.formItem}`}> ...
- 百度地图api的覆盖物样式与bootstrap样式冲突解决办法
使用百度地图api 和 bootstrap ,发现标注样式出现了问题 label左侧 宽度变得非常窄 正常情况下应该是下面这样的: 原因是boostrap样式和百度地图样式冲突了. 解决办法: .ba ...
- Atitit 类库冲突解决方案 httpclient-4.5.2.jar
Atitit 类库冲突解决方案 httpclient-4.5.2.jar 错误提示如下1 版本如下(client and selenium)2 解决流程2 挂载源码 (SSLConnectionSo ...
- SVN代码提交冲突解决方案
SVN代码提交冲突解决方案 1.若你的代码被其他人修改并提交过了,期间你自己也修改过该文件,UPDATE的时候自己代码被覆盖. 右键——>显示日志 查看该文件的更新记录 找到需恢复的版本 右键— ...
- SharePoint 2010 中使用Ztree和EasyUI样式冲突问题
<style type="text/css"> /*解决ztree和SharePoint样式冲突问题*/ .ztree li a { display: inline-b ...
- Git冲突解决方案
Git冲突解决方案 1. 在代码提交时,先更新,若有冲突.先解决冲突.若提交之后在review时才发现无法合并代码时有冲突,需要abandon此次提交的代码. 2. 解决冲突的基本做法,保存本地代 ...
- vue2.0 通过v-html指令渲染的富文本无法修改样式的解决方案
在最近的vue项目中遇到的问题:v-html渲染的富文本,无法在样式表中修改样式: 比如下面的代码,div.descBox里面的p标签的color样式并不是"color: blue" ...
- PC端的软件端口和adb 5037端口冲突解决方案
引用https://www.aliyun.com/jiaocheng/32552.html 阿里云 > 教程中心 > android教程 > PC端的软件端口和adb 50 ...
随机推荐
- How to install nginx in Ubuntu
The steps for installing the nginx on Ubuntu below. 1.install the packages first. apt-get install gc ...
- .net core微服务——gRPC(下)
序 上一篇博客把grpc的概念说了个大概,介绍了proto的数据类型,基本语法,也写了个小demo,是不是没那么难? 今天要从理论到实际,写两个微服务,并利用grpc完成两者之间的通信.只是作为dem ...
- leetcode_1-两数之和_javascript
题目 1.两数之和 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但是,数组中同一个元 ...
- Python 实现邮件发送功能(进阶)
上篇文章已经介绍了利用Python发送文本消息的用法,也在文末遗留了如何发送图片和附件的问题,本章主要来回答这两个问题. 本章主要包含知识点: 1. 如何将图片放到邮件主体中发送 2. 如何发送附 ...
- ref和动态组件
ref--------指引 另一种获取表单值的方法 是Vue环境中一个内置的属性.它可以使用this.$refs可以快速拿到DOM对象.
- ant design pro 实战 : 使用 ztree
应当指出,antd 是有 ztree 组件的,但是太简单,无法满足复杂的业务需求. 所以我还是决定使用zTree. 用 npm | cnpm 或者 yarn | tyarn 安装,这一步略. 在 js ...
- vue 应用 :多语言显示
<template> <div class="hello2"> <page-content> </page-content> < ...
- 题解 洛谷 P3247 【[HNOI2016]最小公倍数】
题意可以转化为是否能找一条从\(u\)到\(v\)的路径,经过的边的\(a\)和\(b\)的最大值恰好都是询问所给定的值. 若只有\(a\)的限制,可以将询问离线,对边和询问都从小到大排序,然后双指针 ...
- 带你理解Lock锁原理
同样是锁,先说说synchronized和lock的区别: synchronized是java关键字,是用c++实现的:而lock是用java类,用java可以实现 synchronized可以锁住代 ...
- DJANGO-天天生鲜项目从0到1-003-用户模块-登录
本项目基于B站UP主‘神奇的老黄’的教学视频‘天天生鲜Django项目’,视频讲的非常好,推荐新手观看学习 https://www.bilibili.com/video/BV1vt41147K8?p= ...