React中处理样式的五种方法
共 18592字,需浏览 38分钟
·
2021-03-20 16:25
关注公众号 前端人,回复“加群”
添加无广告优质学习群
行内样式
const styleApp = {
fontSize: 20,
color: 'red',
}
export default class App extends React.Component {
render() {
return (
<h1 style={ styleApp }>首页面</h1>
)
}
}
note
行内样式使用对象赋值
外部样式
新建一个CSS文件, 在JS文件中引入 CSS文件
import "./App.css"
CSS的模块化
CSS的模块化命名必须是 xxx.module.css
xxx.module.css 中的代码如下:
.error{
color: red;
font-weight: bold;
}
使用:
引入
import common from "./css/common.module.css"
使用
<h1 className={ common.error }>
错误信息
根据不同的条件添加不同的样式
这里我们使用 classnames 这个包
安装 npm i classnames
引入 : import classNames from 'classnames';
举个例子
import React, { Component } from 'react'
import classNames from "classnames"
// 引入外部样式
import "./App.css"
export default class App extends Component {
render() {
let h1Class = classNames({
'box1':true,
'box2':true
})
return (
<div className="container">
<h1 className={ h1Class }>这是一个盒子</h1>
</div>
)
}
}
复制代码
styled-components & css in js
安装:
npm i styled-components -S
所谓 css in js, 就是在 js 中写css.
创建一个 style.js 文件:
import styled from "styled-components"
// 创建一个 Container 组件,它将渲染一个附加了样式的 <div> 标签
let Container = styled.div`
width:500px;
height:500px;
background:${ (props)=>props.color };
font-size:30px;
h1{
color:blue
}
`
export {
Container
}
在需要使用的地方先引入该组件,然后当成标签使用,代码如下:
import React, { Component } from 'react'
import { Container } from "./style"
export default class Search extends Component {
render() {
return (
<Container color='gold'>
<h1>Helo React~</h1>
</Container>
)
}
}
复制代码
组件间通信
React是以组件组合的形式组织的。所以在嵌套关系上,就会有四种不同的可能性:
父组件向子组件通信
子组件向父组件通信
没有嵌套关系的组件通信
跨级组件通信
父组件向子组件通信
class ListItem extends Component {
constructor(props) {
super(props);
this.value = this.props.value;
}
render() {
return (
<li>
<span>{this.value}</span>
</li>
)
}
}
export default class App extends Component {
render() {
const list = [1, 2, 3, 4, 5];
return (
<ul>
{list.map((entry, index) => (
<ListItem key={`list-${index}`} value={entry}/>
))}
</ul>
)
}
}
复制代码
子组件向父组件通信
在用React之前的组件开发模式时,常常需要接收组件运行时的状态,这时我们的方法有:
利用回调函数
父组件将一个函数作为props传递给子组件,子组件调用该回调函数,便可以向父组件通信
利用自定义事件机制
举个例子
class Child extends Component {
constructor(props) {
super(props);
this.state = {
msg: '子组件的msg传值'
}
}
// 通过props 调用回调函数传值
trans = () => {
this.props.callback(this.state.msg);
}
render() {
return (
<div>
<button onClick={this.trans}>传值给父组件</button>
</div>
)
}
}
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
msg: '父组件初始msg'
}
}
// 父组件回调函数,更新state,进而更新父组件
callback = (msg) => {
console.log(msg);
// setState方法,修改msg参数,值是由子组件传过来的
// this.setState({ msg })
}
render() {
return (
<div className="App">
<p>{this.state.msg}</p>
<Child callback={this.callback}/>
</div>
)
}
}
复制代码
没有嵌套关系的组件通信
我们就常以 发布/订阅模式来举例子, 这里我们用 node.js Events模块来实现。
好像就是vue中的EventBus方法
note 我们在处理事件的过程中需要注意, componentDidMount 事件中, 如果组件挂载完成, 再订阅事件; 当组件卸载的时候, 在componentWillUnmount 事件中取消事件的订阅。
安装events并引入
1. npm i events --save
2. 新建 Evt.js 导入 events
import { EventEmitter } from 'events'
export default new EventEmitter();
具体是这样的
import React, { Component } from 'react';
// import PropTypes from 'prop-types';
import emitter from './Evt.js';
export default class App extends Component {
handleClick = () => {
emitter.emit('call', 'hello world');
}
render() {
return (
<div>
<button onClick={this.handleClick}>点击</button>
<Custom1/>
</div>
)
}
}
class Custom1 extends Component {
constructor(props) {
super(props);
this.state = {
msg: ''
}
}
componentDidMount() {
emitter.addListener('call', (msg) => {
this.setState({ msg })
})
// emitter.removeListener('call');
}
componentWillUnmount() {
emitter.removeListener('call');
}
render() {
return (
<p style={{color:'red'}}>
{this.state.msg}
</p>
)
}
}
跨级组件通信
所谓跨级组件通信,就是父组件向子组件的子组件通信, 向更深层的子组件通信。一般来说有以下两种方法:
中间组件层层传递props
使用context对象
使用context需要满足两个条件:
上级组件要声明自己支持 context, 并提供一个函数来返回相应的 context对象
子组件要声明自己需要使用 context
下面我们举个例子, 新建三个文件:
App.js 父组件
Sub.js 子组件
SubSub.js 子组件的子组件
App.js
import React, { Component } from 'react';
import PropTypes from "prop-types";
import Sub from "./Sub";
import "./App.css";
export default class App extends Component{
// 父组件声明自己支持 context
static childContextTypes = {
color:PropTypes.string,
callback:PropTypes.func,
}
// 父组件提供一个函数,用来返回相应的 context 对象
getChildContext(){
return{
color:"red",
callback:this.callback.bind(this)
}
}
callback(msg){
console.log(msg)
}
render(){
return(
<div>
<Sub></Sub>
</div>
);
}
}
Sub.js
import React from "react";
import SubSub from "./SubSub";
const Sub = (props) =>{
return(
<div>
<SubSub />
</div>
);
}
export default Sub;
SubSub.js
import React,{ Component } from "react";
import PropTypes from "prop-types";
export default class SubSub extends Component{
// 子组件声明自己需要使用 context
static contextTypes = {
color:PropTypes.string,
callback:PropTypes.func,
}
render(){
const style = { color:this.context.color }
const cb = (msg) => {
return () => {
this.context.callback(msg);
}
}
return(
<div style = { style }>
SUBSUB
<button onClick = { cb("我胡汉三又回来了!") }>点击我</button>
</div>
);
}
}
复制代码
有几点需要注意:
父组件需要声明自己支持 context,并提供context中属性的 PropTypes
static childContextTypes = {
color:PropTypes.string,
callback:PropTypes.func,
}
复制代码
子组件需要声明自己需要使用 context,并提供其需要使用的 context 属性的 PropTypes
static contextTypes = {
color:PropTypes.string,
callback:PropTypes.func,
}
复制代码
父组件需提供一个 getChildContext 函数,以返回一个初始的 context 对象
原文:juejin.cn/post/6931717995576164365
回复 资料包
领取我整理的进阶资料包回复 加群
,加入前端进阶群console.log("文章点赞===文章点在看===你我都快乐")
Bug离我更远了,下班离我更近了