React中处理样式的五种方法

前端人

共 18592字,需浏览 38分钟

 ·

2021-03-20 16:25


关注公众号 前端人,回复“加群

添加无广告优质学习群

行内样式

const styleApp = {  
    fontSize20,  
    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.

  1. 创建一个 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  
}  
  1. 在需要使用的地方先引入该组件,然后当成标签使用,代码如下:
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 = [12345];  
        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离我更远了,下班离我更近了


浏览 56
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报