ReactP6_React的组件化开发(一)_React组件化_类组件_render函数返回值_函数组件_生命周期及函数_组件嵌套以及通信


这边是react学习笔记,期间加入了大量自己的理解,用于加强印象,若有错误之处还请多多指出

React组件化

组件化思想的应用:

把一个解决能力范围外的大问题拆解成一个个能力范围内的小问题以及可以理解的小问题之间的关系

个人一直理解的是拆成小问题而忽略了问题之间的关系,我觉得这句话对我思想上的帮助很大

在开发过程中,尽可能的将页面拆分成一个个小的、可复用的组件

让代码更加方便组织和管理,并且扩展性也更强。

React的组件相对于Vue更加的灵活和多样,按照不同的方式可以分成很多类组件:

  • 根绝定义方式,可以分为:

    函数组件(Functional Component )

    类组件(Class Component)

  • 根据组件内部是否有状态需要维护,可以分成:

    无状态组件(Stateless Component )

    有状态组件(Stateful Component);

  • 根据组件的不同职责,可以分成:

    展示型组件(Presentational Component)

    容器型组件(Container Component);

这些概念有很多重叠,但是他们最主要是关注数据逻辑和UI展示的分离

函数组件、无状态组件、展示型组件主要关注UI的展示

类组件、有状态组件、容器型组件主要关注数据逻辑

类组件

组件的名称是大写字符开头(无论类组件还是函数组件)

类组件需要继承自 React.Component

类组件必须实现render函数

在ES6之前,可以通过create-react-class 模块来定义类组件,但是目前官网建议我们使用ES6的class类定义

使用class定义一个组件:

定义组件
这里面state内容声明是错误的!这儿只是代表能有多个变量被管理的意思

constructor是可选的,通常在constructor中初始化一些数据

this.state中维护的就是我们组件内部的数据

render() 方法是 class 组件中唯一必须实现的方法

render函数返回值

当 render 被调用时,它会检查 this.props 和 this.state 的变化并返回以下类型之一:

  • React 元素:

    通常通过 JSX 创建。

    例如div会被 React 渲染为 DOM 节点,MyComponent会被 React 渲染为自定义组件;

    无论是div还是MyComponent均为 React 元素。

  • 数组或 fragments:使得 render 方法可以返回多个元素
    render返回数组元素

  • Portals:可以渲染子节点到不同的 DOM 子树中。

  • 字符串或数值类型:它们在 DOM 中会被渲染为文本节点

返回数字类型
返回字符串类型

  • 布尔类型或 null:什么都不渲染。

返回null值

函数组件

函数组件是使用function来进行定义的函数,只是这个函数会返回和类组件中render函数返回一样的内容

函数组件有自己的特点(暂时抛开hooks不谈)

  • 没有生命周期,也会被更新并挂载——没有生命周期函数
  • 没有this——组件实例
  • 没有内部状态——state

函数组件

生命周期(重中之重)

React组件从创建到销毁的整个过程,这个过程称之为是React的生命周期

了解组件的生命周期可以让我们在最合适的地方完成自己想要的功能

生命周期的多个阶段:

  • 装载阶段(Mount),组件第一次在DOM树中被渲染的过程;

  • 更新过程(Update),组件状态发生变化,重新更新渲染的过程;

  • 卸载过程(Unmount),组件从DOM树中被移除的过程;

React内部执行到一定阶段时候,组件内部实现的某些函数进行回调,这些函数就是生命周期函数:

我们可以在这些回调函数中编写自己的逻辑代码,来完成自己的需求功能

  • 比如实现componentDidMount函数:组件已经挂载到DOM上时,就会回调

  • 比如实现componentDidUpdate函数:组件已经发生了更新时,就会回调

  • 比如实现componentWillUnmount函数:组件即将被移除时,就会回调

谈React生命周期时,主要谈的类的生命周期,因为函数式组件是没有生命周期函数的(暂时抛开hooks不谈)

官方生命周期图谱
粗略的解释一下三大阶段:

  • 1、挂载mounting阶段,根据constructor中的数据执行render函数,通过react对DOM进行更新(黄色部分是react框架自动执行),随后调用生命周期函数componentDidMount
  • 2、更新updating阶段,根据传入的新参数(new props组件通信用的),或者是执行了对state进行更新的操作(setState)使得react执行重新渲染的操作,亦或是强制执行了更新页面的操作(forceUpdate)都会执行render函数,让react对DOM进行更新,随后调用生命周期函数componentDidUpadate
  • 3、卸载unmouting阶段,组件被卸载之后,随后调用生命周期函数componentWillUnmount函数

这里提到了一个概念:方法和函数的区别——看有没有this,即有没有一个实例联系在一起,有实例联系的叫方法,没有的叫函数

通过代码验证生命周期函数的执行状态:

index.js

import React from "react";
import ReactDOM from "react-dom"
import App from "./App";


ReactDOM.render(<App/>,document.getElementById('root'));

App.js

import React,{ Component } from "react";

export class ChildCpn extends Component{
    render(){
        return(
            <div>这是子组件ChildCpn</div>
        )
    }
    componentWillUnmount(){
        console.log("调用了ChildCpn的componentWillUnmount方法");
    }
}

export default class App extends Component{
    constructor(props){
        super(props);
        this.state = {
            counter : 0,
            isShow : true,
        }
        console.log("执行了constructor方法");
    }
    render(){
        console.log("执行了render方法");
        return (
            <div>
                <div>这是组件App</div>
                <div>{this.state.counter}</div>
                <button onClick={ e => {this.btnclick()}}> increase </button>
                <hr></hr>
                <button onClick={e => {this.isShow()}}>IsShow</button>
                {this.state.isShow && <ChildCpn/>}
            </div>
        )
    }
    componentDidMount(){
        console.log("执行了componentDidMount方法");
    }
    componentDidUpdate(){
        console.log("执行了componentDidUpdate方法");
    }
    btnclick(){
        this.setState({
            counter: this.state.counter + 1
        })
    }
    isShow(){
        this.setState({
            isShow:!this.state.isShow
        })
    }
}

验证效果:

验证效果

生命周期函数

Constructor

如果不初始化 state 或不进行方法绑定,则不需要为 React 组件实现构造函数。

constructor中通常只做两件事情:

  • 通过给 this.state 赋值对象来初始化内部的state

  • 为事件绑定实例(this)

componentDidMount

componentDidMount() 会在组件挂载后(插入 DOM 树中)立即调用。

componentDidMount中通常进行操作:

  • 依赖于DOM的操作

  • 发送网络请求(官方建议)

  • 可以在此处添加一些订阅(会在componentWillUnmount取消订阅,我也不懂什么是订阅

componentDidUpdate

componentDidUpdate() 会在更新后会被立即调用,首次渲染不会执行此方法。

组件更新后,可以在此处对 DOM 进行操作:

  • 若对更新前后的 props 进行了比较,也可以选择在此处进行网络请求(例如,当 props 未发生变化时,则不会执行网络请求)。

componentWillUnmount

componentWillUnmount() 会在组件卸载及销毁之前直接调用。

在此方法中执行必要的清理操作;

  • 清除 timer

  • 取消网络请求

  • 清除在 componentDidMount() 中创建的订阅等

不常用的生命周期函数可自行阅读文档:

https://reactjs.org/docs/state-and-lifecycle.html

组件嵌套以及通信

简单的嵌套内容

function Header(){
    return(
        <div>
            Header内容
        </div>
    )
}

function Content(){
    return(
        <div>
            <ul>
                <li>列表内容1</li>
                <li>列表内容2</li>
                <li>列表内容3</li>
                <li>列表内容4</li>
                <li>列表内容5</li>
            </ul>
        </div>
    )
}

function Footer(){
    return(
        <div>
            Footer内容
        </div>
    )
}

组件的嵌套关系

为了更好的复用和维护组件,在组件化开发思想指导下需要对一个总的项目进行组件拆分,组件之间存在一个类似于父子的从属关系

上面的嵌套逻辑如下,它们存在如下关系

App组件是Header、Content、Footer组件的父组件

相应的,Header、Content、Footer就是App的子组件

组件的通信

在开发过程中,会经常遇到需要组件之间相互进行通信:

  • 如App可能使用了多个Header,每个地方的Header展示的内容不同,那么我们就需要使用者传递给Header一些数据,让其进行展示

  • 如我们在Main中一次性请求了Banner数据和List数据,那么就需要传递给他们来进行展示

  • 也可能是子组件中发生了事件,需要由父组件来完成某些操作,那就需要子组件向父组件传递事件

总之,在一个React项目中,组件之间的通信是非常重要的环节

  • 父组件通过 属性=值 的形式来传递给子组件数据

  • 子组件通过 props 参数获取父组件传递过来的数据

类组件传递:

import React,{ Component } from "react";
import Child from "./Child"

Child.js
export default class App extends Component{
    constructor(props){
        super(props);
        this.state = {
        }
    }
    render(){
        return (
            <div>
                <Child name="d1" age={23} height={1.86}/>//如果使用双引号传递数值,会被作为字符串处理
                <Child name="d2" age={20} height={1.88}/>//传入Number参数需要大括号
            </div>
        )
    }
}

App.js

import React,{ Component } from "react";

export default class Child extends Component{
    constructor(props){
        super(props);
        this.props = props;
    }

    render(){
        const { name, age, height } = this.props;

        return(
            <div>
                <h2>我是子组件</h2>
                <p>传过来的信息有{name + ","+ age + "," + height}</p>
            </div>
        )
    }
}

类组件传递

函数组件传递:
App.js

import React,{ Component } from "react";
import Child from "./Child"


export default class App extends Component{
    constructor(props){
        super(props);
        this.state = {
        }
    }
    render(){
        return (
            <div>
                <Child name="d3" age={18} height={1.68}/>
                <Child name="d4" age={19} height={1.65}/>
            </div>
        )
    }
}

Child.js

import React,{ Component } from "react";

export default function Child(props){
    const {name,age,height} = props;

    return (
        <div>
            <h2>我是子组件</h2>
            <p>传过来的信息有{name + ","+ age + "," + height}</p>
        </div>
    )
}

函数组件传递

参数propTypes

使用PropTypes验证函数值

对于传递给子组件的数据,有时候我们可能希望进行验证,特别是对于大型项目来说

当然,如果你项目中默认继承了Flow或者TypeScript,那么直接就可以进行类型验证

但是,即使我们没有使用Flow或者TypeScript,也可以通过 prop-types 库来进行参数验证

首先在顶部进行引用
代码引用
再对子组件进行相关配置,例如:
验证参数值类型
更多的验证方式可以参照官网介绍

使用PropTypes给子组件参数赋予默认值

如果没有传递,我们希望有默认值,就可以使用defaultProps,代码结构如下:

赋予默认值
在App.js中调用的时候,不需要在子组件的标签里面传入任何参数,得到的结果如下:

默认参数值
当然,能够检查或是设置默认值的参数类型还很多,这儿不多赘述。

以上就是React组件化开发内容的第一部分,内容量比较大,望能够慢慢吸收。。

感谢coderwhy(王红元老师)的课程内容

爱生活,爱猪猪

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值