react 组件通讯与生命周期

在这里插入图片描述

react 组件通讯与生命周期

1. 组件通讯方法

1.1 基本使用

  • 因为组件有“独立”的特点,所以就会产生组件内和组件外两个概念

  • 组件外向组件内传递数据,是通过组件属性 <组件名 属性={} /> 的方式

  • 组件内接受数据,是通过 props 接收传递进来的数据 (函数组件和类组件)

  • 函数组件内通过参数 props 使用传递过来的数据,类组件内通过 this.props 使用传递进来的数据

    使用组件传值

    <Hello name="Jack" age={19} />
    复制代码

    函数组件使用传递进来的数据

    function Hello(props) {
        console.log(props)
        return (
            <div>{props.name}</div>
        )
    }
    复制代码

    类组件使用传递进来的数据

    class Hello extends React.Component {
        render() {
            return (
                <div>{this.props.age}</div>
            )
        }
    }
    复制代码

1.2 特点

  • 可以给组件传递任意类型的数据

  • props 是只读的对象,只能读取属性的值,无法修改对象

  • 注意:使用类组件时,如果写了构造函数,应该将 props 传递给 super(),否则无法在构造函数中获取到 this.props

    class Hello extends React.Component {  
        constructor(props) {
            // 推荐将props传递给父类构造函数
            super(props)
        }
        render() {
            return <div>{this.props.age}</div>
        }
    }
    复制代码

2. 组件通讯的三种方式

  • 父传子
  • 子传父
  • 非父子组件

2.1 父组件传递数据给子组件

  • 父组件确定要传递给子组件的数据,通常是保存在 state 中的数据

  • 给子组件标签添加属性,值为 state 中的数据

  • 子组件中通过 props 接收父组件中传递的数据

    父组件

    class Parent extends React.Component {
        state = { lastName: '王' }  
        render() {
            return (
                <div>
                    传递数据给子组件:<Child name={this.state.lastName} />
                </div>
            )
        }
    }
    复制代码

    子组件

    function Child(props) {
        return <div>子组件接收到的数据:{props.lastName}</div>
    }
    复制代码

2.2 子组件传递数据给父组件

利用回调函数,父组件提供回调,子组件调用,将要传递的数据作为回掉函数的参数

  • 父组件定义一个回调函数(用于接收数据)

  • 父组件将回调函数作为属性的值,传递给子组件

  • 子组件通过 props 获取到回调函数并调用,回调函数的参数,将作为数据传回到父组件中

    父组件

    class Parent extends React.Component {
        // 传递给子组件的函数
        getChildMsg = (msg) => {
            console.log('接收到子组件数据', msg)
        }
        render() {
            return (
                <div>
                    子组件:<Child sendMsg={this.getChildMsg} />
                </div>
            )
        }
    }
    复制代码

    子组件

    class Child extends React.Component {
        state = { childMsg: 'React’ }
        handleClick = () => {
            this.props.sendMsg(this.state.childMsg)
        }
        render() {
            return (
                <button onClick={this.handleClick}>点我,给父组件传递数据</button>
            }
        )
    }
    复制代码

2.3 非父子组件

  • 将共享状态提升到最近的公共父组件中,由公共父组件管理这个状态
  • 状态提升
  • 公共父组件职责: 1. 提供共享状态 2. 提供操作共享状态的方法
  • 要通讯的子组件只需要通过 props 接收状态或操作状态的方法

3. Context

非父子组件传值需要借助于公共的父组件进行间接传递,比较繁琐。这里推荐使用 Context 这种跨组件传递数据的方式

使用步骤

  1. 调用 React.createContext() 创建 Provider 和 Comsumer 两个组件

    const { Provider, Comsumer } = React.createContext()
    复制代码
  2. 使用 Provider 组件作为父节点

    <Provider>
        <div className="App">
            <Child />
        </div>
    </Provider>
    复制代码
  3. 设置 value 属性,表示要传递的数据

    <Provider value="pink">
        <div className="App">
            <Child />
        </div>
    </Provider>
    复制代码
  4. 调用 Comsumer 组件接收数据

    <Comsumer>
        { data => <h1>接收到的数据:{ data }</h1> }    
    </Comsumer>
    复制代码

总结

  1. 如果来年各个组件是多层嵌套可以使用 Context 实现组件通讯
  2. Context 提供了两个组件:Provider 和 Comsumer
  3. Provider 组件:用来提供数据
  4. Comsumer 组件:用来消费数据

4. props 深入

4.1 children 属性

  • children 属性:表示组件标签的子节点。当组件标签有子节点时,props 就会有该属性

  • children 属性与普通的 props 一样,值可以是任意值

    function Hello(props) {
        return (
            <div>
                组件的子节点:{props.children}
            </div>
        )
    }
    // 此时 children 中就是 “我是子节点”
    <Hello>我是子节点</Hello>
    复制代码

4.2 props 校验

  • 对于组件来说,props 是外部数据的容器,无法保证组件使用者传入什么格式的数据

  • 如果传入的数据格式不对,可能会导致组件内部报错

  • 关键问题:除了语法报错信息之外没有额外错误提示

    // 创建的组件  
    function App(props) {
        const arr = props.colors
        const list = arr.map((item, index) => <li key={index}>{item}</li>)
        return (
            <ul>{list}</ul>
        )
    }
    
    // 使用组件时
    <App colors={19} />
    复制代码
  • props 校验:允许在创建组件的时候,就指定 props 的类型、格式等

  • 作用:捕获使用组件时因为 props 导致的错误,给出明确的错误提示,增强组建的健壮性

    App.propTypes = {
        colors: PropTypes.array
    }
    复制代码

使用步骤

  1. 安装 prop-types npm i prop-types

  2. 导入 prop-types 包

  3. 使用 组件名.propTypes = {} 来给组件的 props 添加校验规则

  4. 校验规则用过 PropTypes 对象来指定

    import PropTypes from 'prop-types'  
    function App(props) {
        return (
            <h1>Hi, {props.colors}</h1>
        )
    }
    
    App.propTypes = {
        // 约定colors属性为array类型
        // 如果类型不对,则报出明确错误,便于分析错误原因
        colors: PropTypes.array
    }
    复制代码

约束规则

  1. 常见类型:number、 string、 array、bool、func、object

  2. React元素类型:element

  3. 必填项:isRequired

  4. 特定结构的对象:shape({ })

    // 常见类型
    optionalFunc: PropTypes.func,
    // 必选
    requiredFunc: PropTypes.func.isRequired,
    // 特定结构的对象
    optionalObjectWithShape: PropTypes.shape({
        color: PropTypes.string,
        fontSize: PropTypes.number
    })
    复制代码

4.3 props 的默认值

  • 场景:分页组件---> 每页显示条数

  • 作用:给 props 设置默认值,在未传入 props 时生效

    function App(props) {
        return (
            <div>
                此处展示props的默认值:{props.pageSize}
            </div>
        )
    }
    // 设置默认值
    App.defaultProps = {
        pageSize: 10
    }
    // 不传入pageSize属性
    <App />
    复制代码

5. 组件的生命周期

5.1 组件生命周期概述

  • 组件的生命周期:组件从被创建到挂载到页面中(显示),再到组件从页面中卸载(消失)的过程
  • 生命周期的每个阶段总是伴随着一些方法调用,这些方法就是生命周期的钩子函数。
  • 钩子函数的作用:为开发人员在不同阶段操作组件提供了时机。
  • 理解了组件的生命周期就是理解了组件的运行方式,可以帮我们实现更复杂的组件和分析组件错误原因等
  • 只有 类组件 才有生命周期。

5.2 生命周期的三个阶段

5.2.1 创建阶段(挂载)

  1. 执行时机

    当组件实例被创建并插入到 DOM 中时

  2. 执行顺序

    constructor() ---> render() ---> componentDidMount()

  3. 作用

    钩子函数 触发时机 作用
    constructor 创建组件时,最先执行 1. 初始化state 2. 为事件处理程序绑定this
    render 每次组件 state 改变触发 渲染 UI( 注意不能调用 setState() )
    componentDidMount 组件挂载后 1. 发送网络请求2. DOM 操作

5.2.2 更新阶段

  1. 执行时机

    1. setSate() 2. forceUpdate() 3. 组件接收到新的 props (以上三者任意一种情况发生,触发组件重新渲染)
  2. 执行顺序

    render() ---> componentDidUpdate()

  3. 作用

    钩子函数 触发时机 作用
    render 每次组件渲染都会触发 渲染 UI
    componentDidUpdate 组件更新后(完成DOM渲染) 1.发送网络请求 2. DOM操作 注意:如果要setState() 必须放在一个if条件中

5.2.3 卸载阶段

  1. 执行时机

    组件从页面消失

  2. 执行顺序

    componentWillUnmount()

  3. 作用

    钩子函数 触发时机 作用
    componentWillUnmount 组件卸载(从页面中消失) 执行清理工作(比如:清理定时器,事件解绑等)

猜你喜欢

转载自juejin.im/post/7032594525893689380