版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
组件的样式
一、简单使用
我们可以为每个组件单独创建一个css样式文件,然后在js文件中,直接导入使用:
// header-nav.js
...
import './header-nav.css'
...
但是这种方式导入的样式会作用于全局。如果要让当前样式只生效于当前组件,可以在选择器上加以限制。比如在声明组件时为当前组件的根元素添加一个唯一的id或类名。然后在样式列表中加上这个选择器标识即可:
// header-nav.js
...
class HeaderNav extends React.Component {
render() {
return (
<div className="header-nav">
<div></div>
<div></div>
</div>
);
}
}
...
/* header-nav.css */
.header-nav div {
// style list
}
二、React的styled-components
React 是组件结构,强制要求把 HTML、CSS、JavaScript 写在一起,以此形成组件低耦合、高复用的特点。所以在React中,组件的结构、样式和逻辑都要使用JS(TS)完成。
所以在React中,编写组件的样式,要用CSS in JS(文末有具体介绍的文档链接),CSS in JS的库有很多中,本文介绍styled-components(较为主流的CSS in JS库)。
- 安装styled-components
npm install --save styled-components
我安装完之后项目无法启动了,报的错是
react-scripts: command not found
重新安装了一下node_modules文件夹就好了
npm i
- 全局的样式
styled-componentsV4之前的版本使用injectGlobal创建全局的样式。V4将injectGlobal移除了,要创建全局的样式需要使用createGlobalStyle,并在组件中以子组件的形式调用。
全局的样式封装
// src/style.js
import { createGlobalStyle } from "styled-components";
const GlobalStyle = createGlobalStyle`
body {
color: #333;
font-size: 16px;
padding: 30px;
}
`;
export default GlobalStyle
全局的样式调用
// App.js
...
import GlobalStyle from './style'
...
class App extends Component {
render() {
return (
<div className="App">
<GlobalStyle />
</div>
);
}
}
...
注:一般情况下我们都利用createGlobalStyle做整个项目的样式重置(reset)。
- 样式化的组件
通过上面的全局样式示范,我们能看到,styled-components删除了组件和样式之间的映射。当定义样式时实际上是在创建一个普通的React组件,只不过其中附加了样式。
样式化组件的封装
// src/components/header-nav/style.js
import styled from 'styled-components'
export const Title = styled.div`
font-size: 1.5rem;
color: palevioletred;
`;
样式化组件的调用
// src/components/header-nav/header-nav.js
import React from 'react'
import { Title } from './style'
class HeaderNav extends React.Component{
render() {
return (
<div className="header-nav">
<div className="box1">你凝视着深渊,深渊也凝视着你。</div>
<Title>
<div className="box2">我的眼睛注视着万物。</div>
</Title>
</div>
);
}
}
export default HeaderNav
在浏览器中的具体呈现效果:
经过解析的DOM结构:
注:
- 在封装样式时,声明了Title组件,是一个div标签(styled.div,如果声明时写了styled.h1,那Title就是h1标签);
- Title可以被复用(样式化的组件一旦被声明,只要导入,就可在任意位置复用);
- Title不仅被解析成了div,还自动被添加了一个选择器,这个选择器是styled-components自动添加的,方便代码复用;
- 样式化的组件调用时,样式生效于被调用的局部,非全局。
- 样式化组件的嵌套
封装
// src/components/header-nav/style.js
import styled from 'styled-components'
export const Title = styled.div`
font-size: 1.5rem;
color: palevioletred;
`;
export const Wrapper = styled.div`
font-weight: bolder;
`;
调用
// src/components/header-nav/header-nav.js
import React from 'react'
import { Wrapper,Title } from './style'
class HeaderNav extends React.Component{
render() {
return (
<Wrapper>
<Title>
只有能被明日的我们铭记,今天才有意义。
</Title>
</Wrapper>
);
}
}
export default HeaderNav
注:样式化组件嵌套时,子组件会继承父组件的样式。
- 样式化组件的参数
一个样式化组件被封装,有些样式可能需要在被调用的时候根据代码上下文才能确定,所以styled-components允许在封装样式组建时传参。
封装
// src/components/header-nav/style.js
import styled from 'styled-components'
export const Title = styled.div`
font-size: 1.5rem;
color: ${props => props.type == 'success' ? 'green' :
props.type == 'warning' ? 'orange' : '#444'};
`;
export const Wrapper = styled.div`
font-weight: bolder;
`;
调用
// src/components/header-nav/header-nav.js
import React from 'react'
import { Wrapper,Title } from './style'
class HeaderNav extends React.Component{
render() {
return (
<Wrapper>
<Title type="warning">只有能被明日的我们铭记,今天才有意义。</Title>
<Title type="success">生命无法承载意义,但你的死亡却可以。</Title>
</Wrapper>
);
}
}
export default HeaderNav
- 样式化组件中的子选择器
封装
// src/components/header-nav/style.js
...
// 封装Wrapper组件的同时封装其子选择器.box的样式,如果在Wrapp组件中,某个元素的类名为box,就会自动生效
export const Wrapper = styled.div`
font-weight: bolder;
.box {
background: #eee;
padding: 20px;
}
`;
...
这些示例都是基本操作,实际上styled-components提供了很多样式编写方式,具体请查看文档。