父组件向孙子组件传值(Context)特性

引言

在我们React组件开发中,当一个父组件的想要往自己的子孙组件传值的时候,可以使用 props属性,但是其每一个子组件,都要向下传递数据,这样造成的数据的耦合性,所以在 React 官方文档中 提供了 context特性来解决,这个问题。

父子组件之间的通信

我们先看一下React中,父子组件通信的机制,父子组件的通信是通过props进行数据的传递:

  1. 父组件向子组件传递数据(状态)时,是在调用子组件的时候通过参数传递给子组件,子组件通过this.props进行接收;
  2. 子组件如果更改父组件的一些属性,则是通过父组件定义的方法来传递给子组件,子组件调用更改;
  3. 如果父组件想要更改子组件的一些状态时,通过ref进行标记,可以获取子组件的所有信息,从而调用子组件的方法和值;

但是,如果层级很多呢,是否需要多个props进行逐层的传递?答案是否定的,React的advanced(高级)中指出了context,优雅的解决这个问题。

好的,接下来我们来介绍一下这个特性Context

我们知道,在JS中context指的是函数的执行上下文,函数被调用时,this指向谁,谁就是当前的执行上下文;

  1. react中的context是什么呢?官方文档给出:
    • Context 通过组件树提供了一个传递数据的方法,从而避免了在每一个层级手动的传递 props 属性。

文档也没具体给出context到底是什么,而是告诉我们context能干什么,也就是说,如果我们不想通过props实现组件树的逐层传递数据,则可以使用context实现跨层级进行数据传递!

如何使用 Context 呢?

context api给出三个概念:React.createContext()、Provider、Consumer;

  1. React.createContext()
这个方法用来创建context对象,并包含Provider、Consumer两个组件 <Provider />、<Consumer />

const {Provider, Consumer} = React.createContext();
  1. Provider
数据的生产者,通过value属性接收存储的公共状态,来传递给子组件或后代组件

eg:

<Provider value={/* some value */}>
  1. Consumer
数据的消费者,通过订阅Provider传入的context的值,来实时更新当前组件的状态

eg: 

<Consumer>
  {value => /* render something based on the context value */}
</Consumer>

值得一提的是每当Provider的值发生改变时, 作为Provider后代的所有Consumers都会重新渲染
props单向数据流动:

如果觉得Props传递数据很繁琐,可以采用context,进行跨组件传递数据

再最外层的组件上,通过生产者Provider组件进行包裹,并存储共享数据到value中,当然可以是任何数据类型。后带需要用到共享数据的组件均可通过Consumer进行数据获取

扫描二维码关注公众号,回复: 8483894 查看本文章

代码演示


import React from 'react'
import ReactDOM from 'react-dom'

// 创建一个 textcont 特性的
const {Provider,Consumer} = React.createContext('顶顶顶')

class Person extends React.Component{
    constructor(props){
        super(props)


        this.state = {
            color : 'red'
        }
    }


    render(){
        return (
                 <Provider value={this.state.color}>
                        <h1>我是父组件</h1>
                        <Son></Son>
                </Provider>
        );
    }
}



class Son extends Person{
    render(){
        return <div>
            <h3>我是子组件</h3>
            <Son1></Son1>
        </div>
    }
}



class Son1 extends Son{
    render(){
        return (
            <Consumer>
                {
                    (color) => <div>
                        <h6 style={{color}}>我是孙子组件-----{color}</h6>
                    </div>
                }
            </Consumer>
        );
        
    }
}



ReactDOM.render(<div>
    <Person></Person>
</div>,document.getElementById('app'))

参考作品出处:
https://segmentfault.com/a/1190000017758300

猜你喜欢

转载自www.cnblogs.com/ifon/p/11514307.html
今日推荐